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

forked from trevato/cs

The range becomes a game without a renderer: seeded pop-up targets, a traced shot, a clock and a score #41

shipped production is serving it opened this has it
opened this

The finale #13 needs a room drawn in WebGL (#5) and movement from the engine's physics (#3), and both sit behind an unmerged pull; the half of it that needs neither — the targets, the shot, the clock and the score — can land now and be held by headless tests.

Done looks like

  • [ ] src/range/targets.ts is plain data in, plain data out: a seeded spawn from the engine's rng places targets as Boxes in front of the shooter, each with a lifetime; step(state, dt) pops them up and retires them; shoot(state, eye, direction) traces with the engine's rayBox/traceWorld and returns the target it hit or nothing, folding the shot and hit counts in.
  • [ ] A clock: a run lasts a fixed number of seconds, ends, stops accepting shots, and reports score, hits, shots and accuracy. Enter starts the next one.
  • [ ] src/range/targets.test.ts would fail without the module: the same seed spawns the same targets twice, a ray down the barrel hits, a ray past it misses, a retired target cannot be hit, accuracy is what a hand count says, and the clock at zero refuses a shot.
  • [ ] src/range/main.ts steps it with the loop it already has, and fire shoots along the current yaw/pitch — the direction is the engine's angleVectors and nothing else. readout.ts gains the score, the clock and the live targets as blips on the horizon: enough that a person can play it with a mouse today and watch the number move.
  • [ ] Still nothing from src/client/: independence.test.ts passes untouched. No endpoint, no table, no cookie — a best score, if it is kept at all, stays in localStorage.
  • [ ] The range page's prose says what is real now and what still waits for the renderer, in one paragraph.
  • [ ] range's ceiling in scripts/build.ts is either still met or raised in a line of the pull that says what was added; the bundle is rebuilt and committed, and bun test is green. Say what /range answers in and what the bundle weighs.

Files I expect to change

src/range/targets.ts, src/range/targets.test.ts (new), src/range/main.ts, src/range/readout.ts, src/range/readout.test.ts, src/pages/range.ts, scripts/build.ts (only if the ceiling moves), static/range.<hash>.js, README.md (a line).

Risks

Scope is the failure mode: no room mesh, no atlas, no WebGL, no movement, no bots. A target is a box in space and the view stays the 2D horizon until #5 and #3 land — a blip is a target projected onto that horizon, not a second renderer. #33 is editing the range page's markup right now, so keep the prose change to one paragraph and rebase rather than merge. #13 keeps the room, the atlas, the movement tuning and the drawn scene; it waits for this.

Suggested: Vesper — a seeded state with a step, a clock and a score is that brief exactly.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs