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

forked from trevato/cs · proposes

spectating is super buggy. i want it buttery smooth #146

Merged opened this in answer to

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

Merged

Pushed; 638 tests pass and the app boots with `/` answering in 8 ms.

shipped production is serving it deploy ae07c2d

opened this

Pushed; 638 tests pass and the app boots with / answering in 8 ms.

Spectating was one line — players.find(p => p.alive && p.team === me.team) on every frame — and four bugs: the watched player's model was still drawn a hull thick in front of the lens, the choice was whatever the roster order said and could not be changed, the camera was written straight from the 64 Hz simulation so it moved in staircases and snapped wherever a bot's aim snapped, and a wiped side with the bomb still ticking left you staring out of your own corpse. src/client/spectate.ts is now the only thing that decides any of it: the choice, kept until they die or you ask for another; the order it moves in (your side while any of it stands, everyone alive once none does); and an exponential ease onto their eye framed in seconds, so it is the same motion at 30 fps and at 144, with a hard cut on a change of target or a teleport. Your own view is never eased — that would be input lag on your own mouse. It costs 0.35 µs a frame and allocates nothing.

buildScene and drawHud take the player the eye belongs to, so the watched body is the one left out, the gun in view is theirs, the HUD reads their health, armour, magazine and defuse bar, and the round is heard from their ears rather than from where you fell. Fire walks to the next player on your side and aim walks back, which are the actions the touch pads already carry, so a phone gets it without a new button; the HUD names whose eyes these are in their team's colour, above the bottom row so it clears the health and the ammo at 360 px.

In the preview: start a match, die (or set a teammate on fire and wait), and watch the banner, the eased follow and the trigger cycling. What I did not do: free-look or a third-person chase camera while dead — the follow is first-person only, and the mouse still does nothing while you are dead. The one test I changed rather than added is the dead-player banner in hud.test.ts: its sentence is now only what you see when there is genuinely nobody left to watch, which is a deliberate behaviour change, not a wrong test. The app bundle grew 1,496 raw / 550 gzipped bytes and fits today's ceiling with 1,772 raw to spare; src/games.ts records the measurement.

🤖 Generated with Claude Code

Closes #133

commented

Merged and pushed; 666 tests pass and the app boots with / answering in 17 ms.

Spectating was one line — players.find(p => p.alive && p.team === me.team) on every frame — and four bugs: the watched player's model was still drawn a hull thick in front of the lens, the choice was whatever the roster order said and could not be changed, the camera was written straight from the 64 Hz simulation so it moved in staircases and snapped wherever a bot's aim snapped, and a wiped side with the bomb still ticking left you staring out of your own corpse. src/client/spectate.ts is now the only thing that decides any of it: the choice, kept until they die or you ask for another; the order it moves in (your side while any of it stands, everyone alive once none does); and an exponential ease onto their eye framed in seconds, so it is the same motion at 30 fps and at 144, with a hard cut on a change of target or a teleport. Your own view is never eased — that would be input lag on your own mouse. It costs 0.35 µs a frame and allocates nothing.

buildScene and drawHud take the player the eye belongs to, so the watched body is the one left out, the gun in view is theirs, the HUD reads their health, armour, magazine and defuse bar, and the round is heard from their ears rather than from where you fell. Fire walks to the next player on your side and aim walks back, which are the actions the touch pads already carry, so a phone gets it without a new button; the HUD names whose eyes these are in their team's colour, above the bottom row so it clears the health and the ammo at 360 px.

Three files needed both sides of the merge with main: onAction answers buy, then full screen, then the spectator's fire and aim; the key hint lists F for full screen with the spectator line under it; and games.ts carries both size logs, with #133 remeasured on top of #132 and #138 at 1,488 raw / 579 gzipped bytes — app 79,454 raw / 36,638 gzipped against the 82,000 / 38,000 ceiling #138 raised, so no ceiling moves. All three bundles are rebuilt and committed.

In the preview: start a match on either map, die, and watch the banner, the eased follow and the trigger cycling. What I did not do: free-look or a third-person chase camera while dead — the follow is first-person only, and the mouse still does nothing while you are dead. The one test I changed rather than added is the dead-player banner in hud.test.ts: its sentence is now only what you see when there is genuinely nobody left to watch, which is a deliberate behaviour change, not a wrong test.

🤖 Generated with Claude Code

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs