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

forked from trevato/cs · proposes

The readout becomes engine: a 2D overlay the HUD draws through, and a second game can too #158

Merged opened this

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

Merged

`src/client/hud.ts` now draws through `src/engine/overlay.ts` — the scale, the pad, the three scaled fonts, the scrim, a line of text with an alignment and a fade, the crosshair, the progress bar, the right-aligned columns and the `m:ss` clock are all the engine's, the same tools `src/range/readout.ts` uses. What is left in the file is Counter-Strike's and nothing else: where a thing sits, what co…

shipped production is serving it deploy ae07c2d

opened this

src/client/hud.ts now draws through src/engine/overlay.ts — the scale, the pad, the three scaled fonts, the scrim, a line of text with an alignment and a fade, the crosshair, the progress bar, the right-aligned columns and the m:ss clock are all the engine's, the same tools src/range/readout.ts uses. What is left in the file is Counter-Strike's and nothing else: where a thing sits, what colour a team is, which phases have a clock, and the words. 286 lines to 253.

I did not tune a number, and the proof is a recording rather than an eyeball: every call drawHud makes, with the brush that made it, was captured across nine worlds (fresh, busy, busy-with-scoreboard, scoped, knife, planting, dead-alone, spectating, between-rounds) at 360, 1280 and 1920 wide — 1,125 calls — on main and on this branch. The two streams are identical but for two things that draw the same pixels: each crosshair arm is stroked from its outer end inwards rather than outwards (the same segment, and hud.test.ts's helper now reads the arm's near and far ends rather than its first and second call), and nine fillRects carry a different leftover textAlign, which a rectangle does not read. Same 4 + spread * 14 gap and 7-unit arms, same 30/19/15px fonts, same rgba(12, 14, 18, 0.55), same team colours, same 8-second fade, same 240×44 and 260×14 bars, same columns at the same 90-unit stride.

The tools are built once per surface and size, not once a frame; the new test in hud.test.ts turns a phone sideways to say the cache notices the resize, and fails if the size is dropped from its key. Measured at 1920×1080 onto a no-op paint: 0.0027 ms a frame and 0.0049 ms with the scoreboard open, against 0.0026 and 0.0056 before. The app bundle grew 483 raw / 498 gzipped bytes rather than shrinking — a tool set is bundled whole, the same thing #49 cost the range — so src/games.ts now says that where it had predicted the opposite; it fits its ceiling with 2,063 raw bytes to spare and no ceiling moved. bun test is 684 green and static/app.024b05a3b5.js is committed.

Worth a look on the preview: the HUD at 360px and at 1920px — the clock bar and the two scores, the kill feed fading down the right, and the scoreboard held open, which is the part with the most moved arithmetic in it. The hit markers and the scope mask stayed in the HUD: a diagonal marker that grows with age is not a shape the overlay hands out, and I chose not to widen crosshair to fit it.

🤖 Generated with Claude Code

Closes #18

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs