HTML5 · Canvas 2D · Vanilla JS · 60 FPS

BREAK/OUT

60FPS
400×600FIELD
8×4GRID
0BEST
CRT-400 · ONLINE RUN 01
8 COL × 4 ROW · 50×20 X 170
01

Geometry

32 bricks, 8 × 4. Each cell is 50 × 20: x = col × 50, y = brickTop + row × 20. Paddle 60 × 10 at y = 580, clamped to 0 – 340.

02

Constant magnitude

Velocity is renormalized every fixed step to the target speed (3.0 → 4.0 px/frame as the field clears). Reflections flip a component; they never stretch the vector.

03

Paddle angle

Contact offset from paddle centre maps to a ±60° exit cone, with a touch of paddle momentum as english. A vertical-only bounce is impossible.

04

One hit per step

AABB tests pick the shallowest-penetration brick, resolve it on its own axis, then lock that brick id for 8 steps. No double burns, no brick tunneling, no stuck ball.

05

Fixed timestep

requestAnimationFrame feeds a 60 Hz accumulator, so 120 Hz phones and 60 Hz monitors see identical physics and identical collision behaviour.

Edge cases handled 08

  • Launch vector starts at dx = 2, dy = −2.8 (normalized) — never straight up, and it alternates sides.
  • Minimum |dy| floor stops the ball grinding horizontally forever.
  • Paddle side and underside faces reflect dx / dy correctly — the paddle is a real solid, not a trampoline line.
  • Ball resting inside a brick after impact is ejected along the collision normal.
  • Multiple overlapping bricks: only the nearest is resolved per frame.
  • Life loss re-docks the ball and counts down before re-launch.
  • Canvas backing store rescales to devicePixelRatio; layout survives portrait and landscape.
  • Tab-hidden auto-pause; audio unlocks on first gesture.
NO LIBRARIES // requestAnimationFrame // AABB + NORMAL RESOLUTION // 3 LIVES // 320 POINT MAX // WEB-AUDIO BLIPS // PARTICLE SHATTER // TOUCH + KEYBOARD //