games: smooth the ball in pong and breakout - #373
Merged
Conversation
Three separate things were making the ball jiggle, and only one of them was about the ball. The clock was re-armed off every keypress. A held arrow key does not arrive as one key, it arrives as a burst of repeats, and each one cancelled the pending tick and started the period again — so at any repeat rate faster than the tick, the ball stopped dead for as long as you steered and then lurched. Measured on pong at a 30/s repeat: 0 ticks in four seconds. The clock now runs on its own deadline, and a keypress may only pull the next tick nearer, never push it away. Chess still gets its fast reply; the ball no longer waits for you. Pong and breakout ticked at 55 and 50ms. The ball can only be drawn on whole cells, so at fifteen columns a second it advanced a cell on six ticks out of seven and stood still on the seventh — and that stalled frame, three times a second, is the jiggle. Both now tick at 16ms with the speeds scaled to match, so the ball is in the same place at the same moment and the stall is 16ms instead of 55. Jitter between column steps drops from 21ms to 6ms, worst stall from 112ms to 66ms. The tuned constants are kept as they were, written per 55ms and scaled, because they are what makes the machine beatable off the end of the paddle and not from the middle. Redrawing erased the whole board and wrote it again, twenty-one rows for a ball that moved one cell — the erase is a visible blink, and over the pit's socket it is the delay. Only changed rows are written now, skipped over with a cursor-down rather than a newline so a frame at the bottom of the screen cannot scroll it. 15.8 KiB/s down to 2.1 KiB/s. The clock and the painter are shared, so every real-time game in the cabinet gets the same two fixes. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
ThreatCrush Security Scan97 finding(s) HIGH/CRITICAL: 5 | MEDIUM: 41 | LOW: 51
…and 47 more. Full results in the Security tab. Snippets are redacted; ThreatCrush never prints matched credential material. |
This was referenced Aug 12, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
/games pongand/games breakouthad a jiggly ball and a choppy redraw. Three causes, only one of them about the ball.The clock was re-armed off every keypress
A held arrow key arrives as a burst of repeats, not one key. Each repeat cancelled the pending tick and restarted the period, so at any repeat rate faster than the tick the ball stopped dead for as long as you steered, then lurched. Measured on
origin/main, holding the paddle key at 30/s:The clock now runs on its own deadline. A keypress may only pull the next tick nearer, never push it away — chess, whose tick rate depends on whose move it is, still gets its fast reply.
The tick was slower than the eye
The ball can only be drawn on whole cells. At 55ms and fifteen columns a second it advanced a cell on six ticks out of seven and stood still on the seventh; that stalled frame, three times a second, is the jiggle. Both games now tick at 16ms with speeds scaled to match — same ball, same place, same moment, but the stall is 16ms instead of 55.
The tuned constants are kept as written, per 55ms and scaled to the tick, because they are what makes the machine beatable off the end of the paddle and not from the middle. Gameplay speed and difficulty are unchanged.
The redraw erased the whole board
Twenty-one rows rewritten for a ball that moved one cell, and the erase-first is a visible blink. Only changed rows are written now, skipped over with a cursor-down rather than a newline so a frame at the bottom of the screen cannot scroll it. 15.8 KiB/s → 2.1 KiB/s, which is most of the "rendering delay" in the pit.
Higher tick rates are free because of this: a tick that leaves the ball in the same cell renders an identical frame, and identical frames were already never written.
Verification
origin/main).The clock and the painter are shared, so all 22 real-time games get both fixes.
🤖 Generated with Claude Code