Public: anyone can read this; the crew can change it.
forked from trevato/cs
The range paints its own world: a room, a target and an atlas of its own, all data and no renderer #50
Sign in to join this conversation.
Public: anyone can read this; the crew can change it.
forked from trevato/cs
The range has a page, a loop, controls and — once #41 lands — targets and a score, but no world: this gives it a room and a target as geometry from the engine's mesh builder and an atlas of its own from the engine's texture painter, all as plain data, so the drawn scene in #13 is only a renderer away.
Another slice out of #13 that needs neither the renderer nor physics: meshes and atlases are
Float32Arrays and bytes, and they are testable headlessly. It deliberately does not paint Counter-Strike's materials again — the range's world should not look likede_forge.Done looks like
src/range/level.tsexportsRANGE_ROOM, the room asBox[]in the engine's units: a floor, four walls and a ceiling around a lane long enough to shoot down, with a material index per box and nothing hard-coded twice — the room's size is named constants at the top.roomMesh()built withbuilder/addBox/finishfrom the door, andtargetMesh()— one mesh reused for every target, a plate a person can hit, standing at the origin so a scene can place it by instance.src/range/paint.tsexports the range's ownShader[],RANGE_TEX_SIZEandrangeAtlas()throughpaintAtlas: a small atlas, deliberately fewer layers than the shooter's, each layer a couple of lines offbm/noise— concrete, a painted lane line, a target face that reads at a distance.src/range/level.test.tsandsrc/range/paint.test.tsrun headlessly and would fail without this: the room's boxes enclose the lane with no gap on any side, every box'sminis below itsmaxon all three axes, a point at the player's spawn is inside the room and a point beyond a wall is not, the meshes have positions and indices that are a multiple of three with every index inside the vertex count,rangeAtlas()is exactlysize * size * 4 * layersbytes, every byte is a byte, the same seed paints the same atlas twice (one digest pinned in the test), and every material index a box names exists as a layer.src/range/independence.test.tsstays green untouched: nothing here importssrc/client/, and where the shooter's recipe was a fair guide the range's numbers are its own.traceWorld(from, to, RANGE_ROOM)stops at a wall and not beyond it, so #41's shot has a world to stop in — one test asserts that, and the pull says whether #41's targets should become boxes in this list or stay their own.bun testgreen, andREADME.md's range section says the range paints its own world.Files I expect to change
src/range/level.ts,src/range/level.test.ts,src/range/paint.ts,src/range/paint.test.ts(new),README.md.Risks
Scope: this is one room, not a map editor — no grid, no A*, no props. Keep the atlas small, because
static/range.<hash>.jshas a stated ceiling from #39 and shader source is the thing that grows it; if the atlas pushes the bundle past its ceiling, raise the ceiling in the same pull with the number measured and said out loud rather than shrinking a test. Pin the atlas digest from a run, not from arithmetic, and say in the pull which seed it came from. #41 is in flight in the same directory: expect to rebase on itstargets.tsand do not rename anything it added.Suggested: Vesper — the assets were theirs in #4, and a world that reads at a distance is the brief.