World
<World map> mounts a map by name: its ground, the scatter standing on it, the navmesh baked from both, and the daylight. All of it lives as long as the World is mounted. The Player and the Camera go inside it, as does every entity of the scene.
Its props are in WorldProps.
look picks a named look: the sky the models light from, fog, exposure, grading and a post-processing stack, set together.
Scatter
Section titled “Scatter”The scatter is what stands on the ground: trees, rocks, bushes and grass, placed from the map’s seed. A kind that blocks a walker, a tree or a rock, always stands in full: on every device, and in a room on the server and every client, so all of them stop her at the same trunk. scatter thins only what decorates, a bush or a tuft of grass, which she walks through; a game passes a lower share on a weak device to draw less of it.
A map is a value the map schema in @daniel-zarinski/schema accepts: a seed, a size and a cell, its hills, regions, paths and rim. registerMap(name, values) parses it and keeps it under the name; it throws on a value the schema refuses, at registration rather than at mount. readMap(name) throws on a name nobody registered, which a <World map> with that name does as well, into the game’s boundary. The engine registers one map, meadow: a 100 m square centred on the origin, so its edge runs from −50 to 50 m on both x and z.
A game keeps its maps as JSON files under src/maps/, one per map, and registers them all from its app file with registerMaps(import.meta.glob("../maps/*.json", { eager: true })), which names each after its file: src/maps/blockout.json is blockout. A file named meadow.json takes the place of the engine’s meadow. add_map writes a new file, and a tool rewrites one safely, where it could not rewrite a TypeScript module. game map check and game map describe read src/maps/<map>.json when the game has it, and the game’s only map file when no --map is given; a game with several map files names one.
The rim is a bank an actor climbs, and the map’s edge behind it is a wall: nothing walks or jumps off the map, so a game needs no check for a fall. Each wall stands the map’s size above its highest ground, 100 m on meadow; a jumpHeight above that would clear it.
A map’s views are named cameras: an eye, a target, and a vertical field of view, or an ortho span in metres for an orthographic view. A view is a bookmark an agent writes once, at the angle its concept art was drawn from, and shoots again after every edit so the shots compare. frameView(map, name) returns the camera for a name: a views entry as written, a region, a path or a prop framed from 45° above at two and a half radii, or map, which every map answers with the whole ground from straight above. It throws on a name the map has not got, listing the ones it has.
An agent matching the map to concept art takes the map-iterate skill: it writes a view at the art’s angle, edits named entries, checks the map’s facts with game map check, shoots the top-down map view and the concept view, and asks a second agent to score both against the art until they pass or ten rounds are spent.
A map’s props are named objects that stand at a written spot, as a level file in Unity, Godot or Unreal keeps its placed instances. Each prop is one of three kinds:
- A shape:
kindisbox,sphere,cylinderorplane, with asizein metres across, tall and deep, 1 m each by default, and acolor. - A scatter kind:
kindis one of the scatter’s kinds, such astreeRoundorrockBoulder. It stands with the scatter whatever thescattershare, and one that blocks a walker blocks it as the scatter’s own do. It stands at the middle of its kind’s heights. - A model:
modelis a registered model’s name, or a path the game serves, such as/assets/statue.glb, which needs no registration.
Every prop takes a position: [x, z] stands it on the ground there, and [x, y, z] holds it at that height. yaw turns it, in degrees, and scale multiplies its size, as one number or one per axis; a scatter kind takes one number, because the scatter scales a kind evenly. A shape or a model is an entity named for its prop in the devtools tree, which draws with the World’s other views and not headless.
"props": { "tower": { "kind": "box", "position": [0, 0], "size": [4, 12, 4], "color": "#8a8f99" }, "oak": { "kind": "treeRound", "position": [8, -6], "yaw": 30 }, "statue": { "model": "/assets/statue.glb", "position": [-6, 4], "scale": 1.5 }}The ground entity
Section titled “The ground entity”The ground is one entity with the ground, scatter, obstacles and navmesh traits on it, and the day clock is another. useWorldEntity() reads the ground from anywhere inside the World, for UI that wants the map.
Sample
Section titled “Sample”import { Bar, Camera, CameraTarget, Hud, Panel, Player, Slot, usePlayer, World,} from "@daniel-zarinski/engine";import { Coin } from "../components/Coin";import { Chest } from "../components/Chest";import { Yeti } from "../components/Yeti";
export function Run() { const player = usePlayer();
return ( <World map="slope"> <Player /> <Camera follow={CameraTarget.Player} /> <Coin position={[3, 0, 5]} /> <Chest position={[8, 0, 20]} /> <Yeti position={[12, 0, 40]} /> <Hud> <Panel slot={Slot.TopLeft}> <Bar label="Health" value={player.health} maximum={player.maximumHealth} /> </Panel> </Hud> </World> );}Coin, Chest and Yeti are the game’s own components, each wrapping an Entity.