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

Make val feel right end to end — the whole feel pass, measured #16

shipped production is serving it opened this has it
opened this

You are the feel pass. This app is the thing being shown to people, and it plays at a solid 60fps with a clean 30Hz wire — so what is left is not throughput, it is everything that jumps, waits or surprises. Take the whole experience, find what still does that, and prove each fix with a number.

What is already known, so you do not re-derive it

  • Frame rate is fine. 60fps measured on the machine that matters, after the renderer went from 1,512 rays and 1,513 fills a frame to 640 and 394. Press ` `` for the readout: fps, ms/frame, Hz in, ms behind, internal width.
  • The wire is steady. 30.2Hz, p50 33ms, p99 41–48ms, zero gaps over 100ms.
  • Three stutters have been found and fixed, all of them corrections that jumped rather than performance: a server-side wall snap that teleported you 76 units backwards; your own camera being drawn with the treatments meant for other people (late, and slid in on arrival); and the buy phase leaving prediction off so your body stepped at 30Hz under a 60fps render.
  • The player still says it is not smooth. The last two fixes are deployed and unjudged. Start by measuring what is actually happening now rather than trusting that list.

Where to look, in the order I would look

  1. The remaining jumps. Every place the client takes the server's answer outright — anchor, the interpolation's "jumped further than anyone can run" reset, the yaw's correction path. Each is a discontinuity. Count how often they fire during a normal minute of play, and make the common ones hold or ease rather than jump. A correction nobody can see is a correction done right.
  2. Rhythm, not rate. The snapshot arrives every 33ms; the frame draws every 16ms. Anything sampled per-snapshot but drawn per-frame will beat against that. The interpolation delay adapts between 45 and 130ms — find out what it actually sits at and whether it is chasing the jitter rather than absorbing it.
  3. The first ten seconds. Joining mid-round, the buy phase, the first spawn, the first enemy appearing. That is what people will see when this is shown to them, and it is where every fault so far has lived.
  4. Input. Firing, casting, planting — does the screen answer immediately, or at the next snapshot? A local, honest acknowledgement (the gun kicks, the plant bar starts) beats waiting for the server to agree, as long as the server still decides what happened.

The bar

Never trade a boundary for a feeling. The server decides what is true; a client is sent only what it can see; the spawn pen, vision and seat rationing stay exactly as they are. If something cannot be smoothed without sending more, say so rather than sending more.

Numbers in the pull, before and after, for whatever you change — a per-frame step spread, a count of corrections a minute, a frame time, the size of the largest jump. And say what to press in the first ten seconds to feel it.

One warning worth having: the test suite is flaky under load — the seat-taking tests in server.test.ts and client.test.ts share one arena in one process and race for a single rationed address, so a run fails perhaps half the time in that cluster and the deploy gate is a coin flip. Do not chase those failures as if they were yours; if you have budget left at the end, isolating them is worth more than one more polish.

Sign in to join this conversation.

↑↓ navigate ↵ open esc close

Keyboard shortcuts