Public: anyone can read this; the crew can change it.
forked from trevato/cs · proposes · 4 behind
The frame becomes engine: a fixed-step loop and a bindings-driven controller #14
Check · Review · Land · Live done — Landed and live in production.
`src/engine/loop.ts` is the fixed step with nothing of this game in it: `advance(elapsed)` clamps a long frame before banking it, returns whole ticks and keeps the remainder, and `start`/`stop` drive from an injected `requestAnimationFrame` and `now`. `src/engine/controls.ts` takes a bindings table (`{ KeyW: "forward" }`) and hands back a held-action set, a thumb stick and drained look; its surfac…
shipped production is serving it deploy ae07c2d
Sign in to join this conversation.
new above
offline
src/engine/loop.tsis the fixed step with nothing of this game in it:advance(elapsed)clamps a long frame before banking it, returns whole ticks and keeps the remainder, andstart/stopdrive from an injectedrequestAnimationFrameandnow.src/engine/controls.tstakes a bindings table ({ KeyW: "forward" }) and hands back a held-action set, a thumb stick and drained look; its surface, window and document are parameters typed by the two methods it calls, socontrols.test.tsdrives the whole thing — keys, repeat, mouse under lock, the stick,preventDefaultand{ passive: false }on the touch handlers, blur, lost lock, on-screen buttons — with a stub target and no browser.src/client/binding.tsis the game's half:CS_KEYS,CS_MOUSE,CS_TAPand onereadIntent(held, stick)to anInput, pinned bybinding.test.ts.src/client/input.tsis gone;main.tslost the accumulator and the key table and is ~20 lines shorter.Numbers were moved, not tuned: 0.022 and 0.06 look scales, 2.2 sensitivity with its 0.2–12 clamp, 0.38 of the width and 60 px of drag for the stick, 120 ms on jump/reload/buy,
preventDefaulton Tab, Space and every touch handler, and held actions cleared on both blur and lost pointer lock. Two deliberate differences worth a look:detach()now removes every listener it registered rather than the three the old module tracked, and mouse buttons come from a table, so only left fires and right scopes — a middle or side button used to fire, and no longer does.bun testis green at 180 (145 before; 35 new), and the bundle is rebuilt asstatic/app.1ac7f396c7.js(67.6 kB, up 0.7 kB). There is no browser in this sandbox, so I could not read#fpsmyself — that is the one check left for the preview. What I did measure, headlessly: the world step is 0.189 ms at 1/64 over a simulated minute, and the whole per-frame engine path (loop.advance+takeLook+readIntent) is 0.34 µs, about 0.002% of a 16.7 ms frame, so the split costs nothing a frame timer can see. On the preview, start a round and check#fpssits where it did, then confirm WASD, the mouse, Tab, 1/2/3, the buy menu and the touch stick all still answer.🤖 Generated with Claude Code
Closes #10