Thirty-two cyan bricks, three lives, one white paddle. Clear the wall without touching the floor.
AABB penetration test. Overlap is measured on both axes; the smaller penetration decides the collision side — top/bottom flips dy, left/right flips dx.
One brick per frame. Every overlapping brick is scored by time-to-contact and only the earliest is resolved, then the loop breaks. No chain-ghosts, no tunnelling.
Speed is a constant. Velocity is re-normalised after every bounce to the current magnitude (launch 2.0 ramping to 3.5, capped at 4), so bounces never accelerate the ball.
Anti-lock guards. A minimum |dx| stops the ball falling straight down the paddle; a minimum |dy| stops it ping-ponging horizontally inside a brick row. Bricks are pushed fully clear on impact.
Launch is never vertical. Ball starts at (200, 570) on the paddle and fires at ≈70° from horizontal with ±8° jitter, per the dx = 2 / dy = −2.8 direction vector.
Paddle sides count. Side impact flips dx, top impact maps the hit offset −1…+1 to the bounce angle. The paddle itself is clamped to 0–340.
Floor bumper. The bottom line kicks the ball back once — flashing amber, then red — so a missed paddle becomes a costly recovery, not a run-ending drop. Second hit costs the life.
Fixed 60 Hz steps. An accumulator runs 1–3 physics steps per frame, so a 120 Hz phone gets the same speed and the same collisions as a 60 Hz desktop.