Canvas Arcade · Build 8×4 · Vanilla JS
32 bricks, one paddle, a three-pixel ball locked to a constant magnitude. Every bounce is resolved by hand — axis by axis, closest hit first.
No engine, no library. Each frame integrates position once, then resolves walls, the single closest brick, and the paddle — flipping exactly one velocity component and renormalising so the ball never speeds up from a bounce alone.
Tap, click or press Space. The serve vector is (2, −2.8) normalised — a 54° climb, never straight up.
Contact offset drives the exit angle: dead centre returns vertically, the edges throw the ball out to ±65°, with a nudge from paddle motion.
Circle-to-AABB gives the closest point. A wider x-offset flips dx, a wider y-offset flips dy, and the ball is pushed clear of the brick so it can't re-collide.
When several bricks overlap the ball, only the deepest penetration is processed. Everything else waits for the next tick.
The magnitude climbs from 3.44 to 4.00 px/frame as the wall thins — inside the smooth band, never a spike.