Public: anyone can read this; the crew can change it.

forked from trevato/cs · proposes · 4 behind

The range paints its own world: a room, a target and an atlas of its own, all data and no renderer #66

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

The range now has a world, as data: `src/range/level.ts` derives one room from four named numbers (`LANE.back/far/half/height` plus `SHELL`) and builds it as six overlapping slabs — floor, four walls, ceiling, one material index each — so the corners are redundant rather than mitred and there is no seam for a bullet to leave through; `roomMesh()` and `targetMesh()` come out of the engine's `builde…

shipped production is serving it deploy ae07c2d

opened this

The range now has a world, as data: src/range/level.ts derives one room from four named numbers (LANE.back/far/half/height plus SHELL) and builds it as six overlapping slabs — floor, four walls, ceiling, one material index each — so the corners are redundant rather than mitred and there is no seam for a bullet to leave through; roomMesh() and targetMesh() come out of the engine's builder/addBox/finish, the plate standing at the origin at STANDARD.half so a scene places it by instance. src/range/paint.ts paints the range's own atlas through the engine's painter: three 64² layers against the shooter's nine at 128² — a target face (bullseye, ring, field: three bands that still read three at 1,200 units), concrete, and the lane floor whose painted line sits on the tile seam so it runs down the lane every 128 units. Seeds are 101–104, the range's own numbers, and the pinned digest 8ec1fa… came from a run of rangeAtlas() on those seeds at RANGE_TEX_SIZE = 64.

Worth looking at: leaks() in level.test.ts, which casts 324 rays from the middle of the lane at a grid across every inner face (corners included) and is itself checked against a room with a doorway cut in it, so the enclosure test can't pass vacuously; and the trace test, which fires STANDARD.range down +X and asserts the shot stops at LANE.far, a unit short of it is inside and a unit past is not, with all six directions stopping at their own surface.

On #41's targets: they should stay their own list, and this pull assumes that. A plate is a thing with a lifetime and a score that step creates and destroys every second or two, and shoot traces only the standing plates on purpose — folding them into RANGE_ROOM would make a static room mutable and would make a missed shot stop in whatever plate happened to be behind the one aimed at. What they now share is the atlas: RANGE_MAT.PLATE is targets.ts's own PLATE_MAT, imported rather than written twice, and layer 0 of the atlas is the plate face because the game said 0 first. targets.ts is untouched.

Nothing is drawn and main.ts imports neither new module, so both committed bundles are byte-identical and no ceiling moved — range still measures 12,548 raw / 5,726 gzipped against 12,800 / 5,800. While there I corrected the README's bundle table, which still quoted the pre-#49 numbers (11,575 / 5,241). What I did not do: no grid, no props, no cover, no second room, and no scene or renderer — the meshes and the atlas are plain Float32Arrays and bytes waiting for #13. bun test is 417 pass / 0 fail, and / and /range answer in 6 ms and 1 ms locally.

🤖 Generated with Claude Code

Closes #50

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs