Sweep
Velocity is split into sub-steps so no single move exceeds 4 px. Position and previous position are both stored for the face test.
Thirty-two neon blocks, one yellow ball, three balls in reserve. Angle the paddle, clear the grid, don't kiss the floor.
No physics engine. Four explicit passes per sub-step, ordered so the ball can never tunnel through a 20 px brick or re-stick to a face it just bounced off.
Velocity is split into sub-steps so no single move exceeds 4 px. Position and previous position are both stored for the face test.
Circle vs AABB using the closest-point clamp
cx = clamp(bx, x, x+w). Every live brick is measured; the nearest hit wins,
the rest are ignored this frame.
Penetration depth is computed on both axes. The shallower axis is the face
that was actually struck — flip dy for top/bottom, dx for sides,
then push the ball clear by depth + 0.5 px. Speed magnitude is preserved exactly.
Hit position maps to ±60° off the paddle centre, plus a
fraction of paddle velocity. A vertical floor of 0.35 × speed stops flat
ricochets from stalling the rally.