feat: boulders

This commit is contained in:
Dan Finch 2026-08-04 14:02:12 +02:00
parent 9aa0ec6a3f
commit 680e08aadc
7 changed files with 169 additions and 11 deletions

View file

@ -58,7 +58,9 @@ rules live in `.agents/rules/*.md`.
edge peaks. `Terrain.ground` builds the outdoor mesh with a hole for the room;
`Terrain.height` is the shared ground-height sampler for the player), `Tree`
(procedural low-poly oak/spruce geometry, sapling..full via a `growth` knob;
`Tree.build` appends into shared trunk + foliage meshes).
`Tree.build` appends into shared trunk + foliage meshes), `Boulder`
(procedural low-poly rock: a squashed, jittered, part-buried sphere;
`Boulder.build` appends into a shared mesh).
- `app/` — browser glue.
- `main.ts` — game loop, input, preset switching, canvas blit, FPS meter.
- `assets.ts` — load `/assets/*.png``Texture` (zero-copy; ImageData bytes
@ -66,10 +68,11 @@ rules live in `.agents/rules/*.md`.
- `level.ts` — builds the playground: a flat stone-floored room (three thick
walls via `slab`, north side open) in the center of a big grassy `Terrain`
world (~20x across).
Per-texture meshes incl. the outdoor grass `ground` and a scattered forest
Per-texture meshes incl. the outdoor grass `ground`, a scattered forest
(`scatterTrees``trunks`/`oakFoliage`/`spruceFoliage`, `TREE_COUNT`/`_SEED`/
`_REACH`), `Aabb` colliders (incl. grown-tree trunks), NPC position, `Terrain`
config + `GROUND_DIVISIONS`/`GROUND_UV`, sky/cloud config.
`_REACH`) and `boulders` (`scatterBoulders`, `BOULDER_COUNT`/`_SEED`/`_REACH`),
`Aabb` colliders (incl. grown-tree trunks + big boulders), NPC position,
`Terrain` config + `GROUND_DIVISIONS`/`GROUND_UV`, sky/cloud config.
The stone floor is lifted by `FLOOR_LIFT` (a z-bias) so it stays clean over the
terrain skirt that laps under the room edges. Room surfaces are single flat
quads -- no subdivision needed since texturing is perspective-correct; ground
@ -83,9 +86,9 @@ rules live in `.agents/rules/*.md`.
`#fps` meter div (styled inline).
- `scripts/gen-assets.ts` — procedurally draws the placeholder textures and
writes PNGs (hand-rolled encoder via `node:zlib`). Run via `bun run assets`.
- `assets/` — generated `floor/grass/bark/leaf/needle/wall/crate/npc` PNGs
- `assets/` — generated `floor/grass/bark/leaf/needle/rock/wall/crate/npc` PNGs
(`floor` = room stone, `grass` = outdoor ground, `bark`/`leaf`/`needle` = tree
trunk/oak/spruce). Swap for real art anytime;
trunk/oak/spruce, `rock` = boulders). Swap for real art anytime;
filenames are the contract.
- `server/` — Bun server stub. `shared/` — isomorphic slot.
@ -93,8 +96,8 @@ rules live in `.agents/rules/*.md`.
`Player.update` → build `Camera``Camera.viewProjection`
`Sky.render` (fills color + resets depth, replaces a clear) →
`Rasterizer.draw` ground, floor, walls, crate, tree trunks, oak foliage, spruce
foliage (one call per texture) →
`Rasterizer.draw` ground, floor, walls, crate, boulders, tree trunks, oak
foliage, spruce foliage (one call per texture) →
`Sprite.billboard(npc)` drawn via `Rasterizer.draw`
`Framebuffer.quantize``present` (integer-scale, letterboxed blit;
`imageSmoothingEnabled` follows `upscaleFilter`).
@ -152,6 +155,12 @@ canopy blobs (oak) / tiers (spruce); `seed` gives each tree its own wobble.
(one bark trunk mesh, oak-leaf and spruce-needle foliage meshes). `app/level.ts`
`scatterTrees` seeds the forest; add a species by extending the union + a builder.
**Boulders** (`engine/scene/Boulder.ts`) work the same way: `Boulder.build`
appends a squashed, per-vertex-jittered low-poly sphere (seam/pole-safe so it
never cracks) into one shared rock mesh, sunk partway into the ground.
`scatterBoulders` sizes them small→big (biased small) and drops colliders on the
big ones.
## Controls
WASD move · **Shift** run (speed ×`RUN_MULTIPLIER` in `app/player.ts`) · mouse