Canvas Arcade · Cabinet 01 · Credit 01

BREAKOUT

32 cyan bricks. One 6-pixel ball. Three lives and a paddle that decides the angle.

FIELD 400 × 600
GRID 8 × 4 · 50×20
PADDLE 60 × 10 @ y580
BALL ⌀6 · 3.44–3.90 px/f
-- FPS
Model BRK-400 · Vanilla JS
BREAKOUT
PHOSPHOR CRT · 32 BRICK MODE
Rules of engagement
  1. Walls flip an axis, nothing else

    Left, right and the ceiling invert one velocity component and re-seat the ball flush against the surface so it can never sink into the frame.

  2. Paddle angle is a position function

    Contact offset -1 → +1 maps to a ±62° exit vector. Center hits go up; edges rip sideways. A floor on vertical speed blocks infinite horizontal stalls.

  3. Bricks resolve on the shallow axis

    Smallest penetration wins, so a corner graze pushes out the side instead of tunnelling through the row. Only the single closest brick is processed per frame.

  4. Speed is a magnitude, not a pair of numbers

    The vector is renormalised every step to 3.44 → 3.90 px/frame as the wall thins. Bouncing never accelerates or decays the ball.

  5. Three lives, 320 points, one screen

    Drop the ball below y=600 and the run costs a life; the ball re-seats on the paddle and waits for launch input.

Build notes
  • Fixed-timestep accumulator (16.67 ms) — identical physics on 60 Hz, 90 Hz and 120 Hz displays.
  • Static field, grid and vignette pre-rendered to an offscreen canvas; one drawImage per frame.
  • Per-row gradients cached at init — zero gradient allocation inside the render loop.
  • Device pixel ratio capped at 2 for sharp text without mobile fill-rate cost.
  • Touch events bound passive:false; mouse uses pointer events, so no double-fire on hybrid devices.
  • Shake, flash, shards and ball trail all drawn to the same 2D context — no DOM churn during play.
  • Loop pauses on tab blur; canvas keeps its last frame as a resume poster.
  • WebAudio blips synthesised on the fly, created only after a user gesture.