Drag anywhere on screen to slide the paddle · release nothing — tap to launch
Grid 8×4 · 32 bricks · 3 balls · 320 max · canvas 400×600
Drag anywhere on screen to slide the paddle · release nothing — tap to launch
Brick contacts are solved as a slab entry test against the brick rect expanded by the ball radius: the earliest axis-of-entry wins, so hitting a seam between two bricks flips the correct component instead of ping-ponging sideways. Only the nearest contact resolves and destroys a brick per step — the velocity magnitude is preserved, so the ball never gets heavier, never gets stuck.
Paddle returns are angle-steered: the contact offset across the 60px face maps to an exit angle up to ±65°, plus a little carry from paddle momentum, with a floor on |dy| so the ball can never settle into a horizontal loop.
Everything inside the bezel — score, lives, ceiling bar, particles, trails, the CRT overlay and the restart button — is drawn with Canvas 2D on the same 400×600 coordinate space, upscaled by devicePixelRatio for crisp edges. The simulation runs on a fixed accumulator, so a 120 Hz phone plays at exactly the same speed as a 60 Hz desktop.