Cabinet online · sector 7 · 60 fps

Breakout

32 cyan blocks. One 3‑pixel ball. Three lives and a paddle that answers to your finger, your mouse, or your arrow keys.

Model BRK‑400
Grid 8 × 4
Max 320 pts

Ready

Drag anywhere on the screen to steer · tap to launch

Service manual

Everything below runs on vanilla JavaScript and one Canvas context. No engines, no libraries, no image assets — physics stepped at a fixed 60 Hz with a delta accumulator so motion stays identical on 60 Hz and 120 Hz panels.

01

AABB with side resolution

The ball's bounding box is tested against every live brick, the closest intersecting brick wins, and the axis with the smaller penetration decides the flip: top/bottom inverts dy, left/right inverts dx. One brick is consumed per frame, so a corner entry can never tunnel or double-count.

02

Speed is always constant

After every impact the velocity vector is re-normalised back to the target magnitude — 3.45 px/frame at launch, easing to 4.00 as the wall thins. Angle changes never leak energy, and a vertical-stall guard nudges any trajectory that gets too horizontal.

03

The paddle steers, not just reflects

Contact uses closest-point circle/AABB resolution. Hitting the top face maps the offset from centre to a ±60° exit angle; striking the rim or underside pushes the ball sideways instead, so edge saves feel earned rather than random.

04

Three input paths, one target

Pointer moves, keyboard velocity and touch drags all write to a single paddle target that's eased at 42% per step. Touch coordinates are mapped through the canvas's live bounding rect, so the game stays pixel-accurate at any viewport size or orientation.

Edge cases handled

  • Stuck ball — destroyed bricks are flagged before resolution, and the ball is pushed clear of the brick face.
  • Stacked collisions — only the nearest brick resolves each step; the rest are re-tested on the next.
  • Wall/brick overlap — brick row 0 spans the full width, so the top wall is only reachable once a column opens.
  • Paddle clamping — the paddle's x is bounded to 0–340 in both pointer and key paths.
  • Frame spikes — the accumulator caps catch-up at 5 steps, so a background tab never teleports the ball.
  • Retina + perf — the backing store scales with devicePixelRatio (capped at 2) and the background grid is pre-rendered once.
400×600
Canvas field
8×4
Brick grid
3px
Ball radius
320
Max score
0deps
Vanilla JS