Data-driven parks: one heightAt(x,z) evaluated from element JSON drives the editor viewport, collision, test ride, and exported game levels. Ships with Paddo ported from bookquoy, a MODELBEAST panel (gen images, cut bg, image->3D, place farm GLBs as props), image decals + reference underlay tracing, a park design linter (docs/DESIGN_PRINCIPLES.md), THPS-style instant test ride, and a level.js codegen that drops straight into bookquoy. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
50 lines
2.0 KiB
JavaScript
50 lines
2.0 KiB
JavaScript
// SKATEMAKER PRO — exports. A park leaves here two ways:
|
|
// 1. park.json — the native data format
|
|
// 2. level.<name>.js — a drop-in for BOOKQUOY: exports the exact interface
|
|
// bookquoy's js/level.js has (heightAt, normalAt, BOUNDS,
|
|
// RAILS, GAPS, LETTERS, SPAWN, buildLevel). Ship it with
|
|
// parkmath.js + parkbuild.js + assets/uploads/.
|
|
|
|
function download(name, text, type = 'application/octet-stream') {
|
|
const a = document.createElement('a');
|
|
a.href = URL.createObjectURL(new Blob([text], { type }));
|
|
a.download = name;
|
|
a.click();
|
|
setTimeout(() => URL.revokeObjectURL(a.href), 5000);
|
|
}
|
|
|
|
const slug = park => (park.name || 'park').toLowerCase().replace(/[^\w]+/g, '_');
|
|
|
|
export function downloadParkJSON(park) {
|
|
download(slug(park) + '.json', JSON.stringify(park, null, 1), 'application/json');
|
|
}
|
|
|
|
export function generateLevelJS(park) {
|
|
return `// ${park.name} — generated by SKATEMAKER PRO ${new Date().toISOString().slice(0, 10)}
|
|
// Drop-in for BOOKQUOY: copy this file + parkmath.js + parkbuild.js (+ assets/uploads/)
|
|
// into bookquoy/js/ and point main.js/player.js imports at it. Same contract as level.js:
|
|
// heightAt(x,z) is the single source of truth for visuals AND collision.
|
|
import { makeHeightAt, makeNormalAt } from './parkmath.js';
|
|
import { buildParkScene } from './parkbuild.js';
|
|
|
|
export const PARK = ${JSON.stringify(park, null, 1)};
|
|
|
|
export const BOUNDS = PARK.bounds;
|
|
export const RAILS = PARK.rails;
|
|
export const GAPS = PARK.gaps;
|
|
export const LETTERS = PARK.letters;
|
|
export const SPAWN = PARK.spawn;
|
|
export const heightAt = makeHeightAt(PARK);
|
|
export const normalAt = makeNormalAt(heightAt);
|
|
|
|
export function buildLevel(scene) {
|
|
const { ground, letterMeshes } = buildParkScene(scene, PARK);
|
|
return { ground, letterMeshes };
|
|
}
|
|
`;
|
|
}
|
|
|
|
export function downloadLevelJS(park) {
|
|
download('level.' + slug(park) + '.js', generateLevelJS(park), 'text/javascript');
|
|
}
|