← → / mouse · drag on screen for touch · space launch · P pause · R restart
32 bricks. One 6px ball. A 60-pixel slab of white between you and the void.
← → / mouse · drag on screen for touch · space launch · P pause · R restart
Four things that separate a playable brick breaker from a ball that teleports through walls.
The ball is treated as a 6px box against each brick. All four penetration depths are measured, the smallest one wins, and that axis alone flips — so a top strike reverses dy, a side strike reverses dx. The ball is also pushed flush to the face it hit, so it can never be left inside a brick.
Each frame's movement is sliced into sub-steps of ≤1.4px. Bricks are scanned for the closest overlap and only that one is destroyed, with a short cooldown keyed to brick id — no double flips, no chain-reacting row wipes, magnitude always held at 3.44px/frame.
Contact point maps to exit angle: dead centre fires straight up, the tips throw the ball out to ±62°, with a slice of paddle velocity mixed in. A floor on the vertical component (|dy| ≥ 0.30 × speed) kills the infinite horizontal grind.
Physics runs on a 16.6ms accumulator, so a 120Hz phone and a 60Hz monitor solve the same game. Touch events are preventDefault-bound to the canvas and mapped through getBoundingClientRect, so finger position converts to true canvas space at any CSS size, portrait or landscape.