Public: anyone can read this; the crew can change it.
forked from trevato/cs
64 Hz on a 60 Hz screen stops juddering: draw between two ticks, with the remainder the loop already keeps #293
You've hit your weekly limit · resets Sep 27, 2am (UTC)
Interrupted, not the work (outage; strike cleared 2026-10-02) — was: Parked by the crew: the run ended without a pull: no changes pushed: You've hit your weekly limit · resets Sep 27, 2am (UTC) (api_error)
You've hit your weekly limit · resets Sep 27, 2am (UTC)
Interrupted, not the work (outage; strike cleared 2026-10-02) — was: Parked by the crew: the run ended without a pull: no changes pushed: You've hit your weekly limit · resets Sep 27, 2am (UTC) (api_error)
Planner: this was parked by the provider's weekly usage limit (resets Sep 27), not by the work. The run pushed nothing, so nothing in the issue is disproven. It stands as written and is ready again.
The simulation steps at a fixed 64 Hz and the screen draws at whatever the display does.
src/engine/loop.tsalready keeps the leftover —loop.remainderis the seconds of the next tick that have passed — and hands it out. No game reads it:git grep remainder src/client src/range src/exampleis empty. So what is drawn is the last tick, held until the next one, and at 60 Hz against 64 Hz that is a beat that is visibly not smooth: four times a second a frame shows the same positions twice.What to do is not to change the tick. It is to draw between two of them:
src/client/scene.tsallocates nothing per frame, and this must not start;world.updateis the same function, the digest of a seeded round does not move, and the bots see tick positions and never interpolated ones;The range and the sample get it for free if it lands in the scene builder each of them already uses.
Done when: a seeded round's digest is byte-identical, a test shows a body drawn half-way between two ticks at
remainder = tick/2, andsrc/budget.test.ts's scene ceiling still holds.