BRICK/BREAKER

Canvas 400×600 · vanilla js · fixed-step 60fps

Attract

Move the mouse or drag on screen

Collision resolution, not collision response-by-luck

Everything below runs in one <canvas> with no engine: an explicit accumulator loop, nearest-point AABB tests and a single winner per step.

  1. 01

    Fixed-step integration

    Physics runs at a hard 1/60 s tick, decoupled from rAF, so a 120 Hz phone and a 60 Hz laptop get identical trajectories. Long frames are capped at five catch-up steps; the ball is further split into 2 substeps so it can never tunnel through a 20 px brick.

  2. 02

    Nearest-point circle / AABB

    Clamp the ball centre into the brick rect, measure the distance to that closest point, and compare against r = 3. Every overlapping brick is scored, but only the one with the shortest centre distance resolves — the rest wait for the next step, so a corner hit never flips both axes.

  3. 03

    Least-penetration axis

    Overlap on X vs overlap on Y decides the face. The smaller one is the face you actually crossed: flip dy for top/bottom, dx for left/right, then eject the ball by exactly that depth so it can't re-collide inside the block.

  4. 04

    Paddle angle map

    θ = (x − cx) / (w/2) × 58° — dead centre returns straight up, the rim slices it off at a wide cut. After every reflection the velocity is renormalised to the ball's scalar speed, so energy never leaks or compounds; heading is clamped to keep the ball out of pathological horizontal loops.

Constants
Field400 × 600 px
Grid8 × 4 · 50 × 20
Blocks32 · 10 pts · max 320
Paddle60 × 10 @ y 580
Paddle rangex 0 → 340
Ballr 3 · start (200, 570)
Launch vector(±2, −2.8) ≈ 3.44
Speed band3.4 → 3.9 px/frame
Lives3
Tick16.67 ms fixed
Substeps / ball2
Dependencies0