games: draw the ball on half-rows, so it moves like a ball - #376
Merged
Conversation
The clock was fixed last time; the grid was not. A terminal cell is about twice as tall as it is wide, and the ball was drawn one per cell, so the board it moved on had half the resolution going down that it had going across. Two things fall out of that, and both of them read as bad physics rather than as a coarse grid. A step sideways moved the ball one pixel and a step down moved it two. The same ball appeared to travel twice as fast down the table as across it, and a trajectory the maths had at forty-five degrees was drawn at sixty. Worse, the two steps kept their own schedules. Crossing into the next column and crossing into the next row almost never landed on the same tick, so a ball going diagonally did not move diagonally — it hopped sideways, then a tick or two later hopped down. On pong the ball held a cell for four ticks, four ticks, then two and two as a row change split one of those spans, three or four times a second. That is what was left of the jiggle. Half blocks fix both. `▀` and `▄` each fill half a cell, which is close to square, so the ball is drawn on a grid with the same pitch both ways: it steps the same distance whichever way it goes, and a row is two steps rather than one. The biggest single jump a rally can make drops from 2.24 cells to 1.41 — one column and one half-row, never one column and a whole row. Breakout, which is steeper and felt worse, improves most: the time the ball holds one drawn position goes from 1–10 ticks to 1–5, and the jitter on it from ±45ms to ±22ms. It is a better ball, too. A half block is a square pixel moving on a square grid, where `●` was a round dot snapping between positions two of its own heights apart. In breakout the resting ball now sits flush on the paddle. Nothing about the simulation changed — no speed, no angle, no bounce. This is only where the ball is drawn, which is where it was wrong. 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.
Ball physics still read as wrong after #373. That fix was right about the clock — I re-measured and the column steps are now regular, four ticks each — but it left the grid alone, and the grid was the other half of the problem.
What was wrong
A terminal cell is about twice as tall as it is wide, and the ball was drawn one per cell. So the board it moved on had half the resolution going down that it had going across, and two things fell out of that:
The fix
▀and▄each fill half a cell, which is close to square, so the ball is drawn on a grid with the same pitch both ways. It steps the same distance whichever way it goes, and a row is two steps rather than one.Breakout is the steeper game and felt worse; it improves most.
It's a better ball, too — a half block is a square pixel moving on a square grid, where
●was a round dot snapping between positions two of its own heights apart. In breakout the resting ball now sits flush on the paddle.Nothing about the simulation changed. No speed, no angle, no bounce, no tuned constant. This is only where the ball is drawn, which is where it was wrong.
Testing
Three new tests in the shared section, and the middle one is a real regression guard — under the rendering that shipped in v0.45.0 it fails with a 2.24-cell jump:
Full suite: 1852 tests, 0 failures. Frames verified end-to-end through
runGame's incremental repaint — box edges align, no corruption.▀/▄are already used by the breakout paddle, so no new width risk.Not in this PR
vy *= 0.3flattens the ball hard on every one of its returns and rallies drift toward the angle floor. That's balance, not a bug, and games: smooth the ball in pong and breakout #373 deliberately preserved those constants — flagging rather than touching it.🤖 Generated with Claude Code