32 blocks · 3 lives · one 3px yellow ball. Canvas 2D, fixed-timestep AABB, zero dependencies.
Engineering notes
Circle-vs-AABB overlap tested against every live brick. Penetration depth on each axis decides the response — the shallowest overlap resolves first and the loop breaks, so clipping a seam between two bricks flips exactly one axis and never both.
The hit offset is normalised −1…1 across the 60px face and mapped to a ±62° exit angle, then the velocity vector is renormalised to the current speed. Centre contact serves straight up; edge contact throws wide. Side contact flips horizontal instead.
requestAnimationFrame feeds a 1/60s accumulator capped at five catch-up steps. Physics advances in identical slices, so a dropped frame on a mid-range phone can never tunnel a 3px ball through a 20px brick.
Mouse, touch and key states all write to a single paddle target; the paddle eases toward it for wobble-free tracking. The backing store is sized by devicePixelRatio while CSS scales the display box, so the field stays crisp from 320px phones to desktop.