BREAKOUT canvas build · v1.0 · vanilla js · no libraries
FIELD 01STANDBY32 BRICKS
drag to move · tap to launch60 fps

Machine spec

read-out
400 × 600

Logical canvas space, DPR-scaled backing buffer, CSS-fitted from 320px up to desktop.

8 × 4

Brick grid at x = col·50, y = row·20, flush to the field edges — 32 blocks, full-width rows.

+10

Per brick destroyed. Hard ceiling of 320 points, cleared in one perfect life.

3 → 4

Ball speed magnitude in px/frame. Ramps as the wall thins, renormalised on every bounce.

65°

Max paddle deflection. Contact offset across the 60px paddle sets the exit angle — no vertical ping-pong.

Collision & edge cases

Circle vs AABB, single resolution. Every frame is divided into two sub-steps; each sub-step sweeps the ball's bounding box across the brick grid, keeps only the closest overlapping cell, resolves it, then stops scanning. Two bricks can never be consumed in one sub-step.

Side detection. Overlap on both axes is measured against the inflated rect. The smaller penetration defines the reflected axis — dy for top/bottom, dx for left/right — and the ball is separated out of the brick so it cannot re-trigger next frame. A second validation rejects a flip that would leave the ball still overlapping, unsticking corner hits.

Paddle faces. The paddle is a full solid box: top face deflects by contact offset, side faces bounce dx so the ball never tunnels through, and the paddle's own x is clamped to 0…340 so it can never leave the field.

Frame safety. Fixed 60Hz accumulator, max 5 catch-up steps, delta clamped after tab switches. Wall bounce preserves the velocity magnitude — |v| only changes at the paddle, never by accident.