Public: anyone can read this; the crew can change it.
forked from trevato/cs · proposes · 4 behind
The range becomes a game without a renderer: seeded pop-up targets, a traced shot, a clock and a score #51
Check · Review · Land · Live done — Landed and live in production.
`src/range/targets.ts` is the range's game, with no canvas anywhere near it: a seeded `rng` pops plates up as `Box`es down a lane in front of the shooter, each with its own lifetime and worth 100–200 points by how far down the lane it stood; `step(run, dt)` runs those lifetimes and the thirty-second clock and clears the lane when time is up; `shoot(run, eye, direction)` normalises the aim, traces…
shipped production is serving it deploy ae07c2d
Sign in to join this conversation.
new above
offline
src/range/targets.tsis the range's game, with no canvas anywhere near it: a seededrngpops plates up asBoxes down a lane in front of the shooter, each with its own lifetime and worth 100–200 points by how far down the lane it stood;step(run, dt)runs those lifetimes and the thirty-second clock and clears the lane when time is up;shoot(run, eye, direction)normalises the aim, traces the engine's boxes, takes the plate down and folds the hit, the score and the accuracy in — and returns nothing at all for a shot the clock refuses.main.tssteps it in whole 50 Hz ticks, starts a run on the edge of Enter (a held trigger is one shot, a held Enter is one run) and fires alongangleVectors(yaw, pitch).forwardand nothing else;readout.tsleads the panel withscore … best … hits … %and the clock, and draws each standing plate as a square on the existing 2D horizon, placed by the angle from the crosshair and sized by the angle it subtends — a projection, not a second renderer.Worth looking at:
targets.test.tsdials the randomness flat so the geometry is arithmetic (a plate at 512 units, 16 from centre to edge — a ray down the barrel stops at 496, a ray 5° wide of it goes by, since 512·tan5° = 44.8), plus the same seed playing the same run twice, a retired plate that cannot be hit, accuracy by hand count and the clock at zero refusing a shot. The newboot.test.tscase plays the game through the entry against the stub page: lock the pointer, press Enter, read the blip the scene drew, turn onto it in mouse counts, click, and the score moves — then the clock runs out, the trigger stops working and the best of the visit survives into the next run.What I chose not to do: no room, no atlas, no WebGL, no movement, no bots, and no
localStorage— the best score is a variable that dies with the tab, so the page's "nothing on this page is stored" stays literally true. Nothing fromsrc/client/;independence.test.tsis untouched and passes. Scope beyond the issue is two lines: a start button on the touch pad (Enteris otherwise unreachable on a phone) and its assertion insrc/server.test.ts. Page prose is the one paragraph, plus the overlay's own heading and sentence so a player arriving is told what to press.range's ceiling is raised from 7,800/3,600 to 12,800/5,800 bytes — the game module, the engine'straceand the blip projection are what was added — and the bundle is rebuilt and committed at 11,575 bytes raw / 5,241 gzipped./rangeanswers in ~0.9 ms with 7,555 bytes of HTML (5.4 ms cold),bun testis green at 356 tests.🤖 Generated with Claude Code
Closes #41