Breakout Game JavaScript: Resolve Each Brick and Life Once

The ball touches a brick for two frames, but that brick should still earn only one point. After a miss, the ball should wait for the next launch rather than spend the remaining lives while below the board.

Tie both events to a single state transition.

The playable example starts with twelve original bricks, three lives and zero score. It supports Launch, Pause, Resume, Reset, paddle controls and a paused 0.05-second inspection step. Each removed brick scores once; each fully missed ball costs one life and waits. Pausing stops automatic movement so you can inspect one step.

Breakout Game JavaScript: Resolve Each Brick and Life Once
Breakout Game JavaScript: Resolve Each Brick and Life Once
Open the full example ↗

Keep logical geometry separate from display size

Use a 320-by-240 logical board, ball radius 6, initial center (160, 190) and launch velocity (90, −90) pixels per second. The paddle is 60 wide, 10 high, centered initially at x = 160 with top y = 210.

The board has 12 uniquely identified bricks in three rows of four. Brick columns begin at x = 20, 92, 164 and 236; rows begin at y = 30, 48 and 66. Each rectangle is 60 units wide and 12 high. The rectangles use three row colors, making the remaining brick pattern easy to follow.

MDN's scoring and lives lessons discuss removing hit bricks, stopping after the final brick, and decrementing a life before relaunch. Here, the score and remaining count come from the twelve individually tracked bricks. Score and Win, Extra Lives

Score the alive-to-removed transition

Each live brick hit changes its ID to removed and adds one point. The first hit reduces the remaining count from 12 to 11 and raises the score from 0 to 1. A later contact with that removed ID cannot score again.

Derive remaining count from the alive-ID state, and keep score updates in the same event transaction. If one contact event legitimately removes several tied bricks under the declared collision rule, score each unique removed ID once; do not duplicate awards through repeated frame processing.

When zero bricks remain, enter the won state and stop ball processing before continuing miss checks in that frame. No later movement should turn a finished game into a lost life.

Lose one life and wait for Launch

The original miss condition is that the ball is fully below the board: centerY − radius > 240. Begin with three lives. One qualifying miss subtracts one life once and leaves active play immediately.

With lives remaining, reset the ball/paddle for an explicit Launch, preserving the remaining bricks and score. An idle ball cannot continue losing lives while waiting. Zero lives produces a lost terminal state; neither won nor lost advances the ball.

Show score, lives, remaining bricks and state in text alongside Launch, Pause, Resume and Reset. Paddle Left and Right buttons move in 20-unit steps; fresh arrow presses work while the game area has focus. Pointer input must map through the actual displayed rectangle to logical coordinates. The text status exposes the game state alongside the canvas; it does not provide an equivalent way to perceive every ball movement.

Prevent a reset from leaving two loops alive

Keep one animation-loop owner. Clamp elapsed time under an explicitly selected bound and reset the timestamp when resuming or launching, so time spent paused does not become one large movement step. The example clamps each animation update to 50 milliseconds and also offers a manual 0.05-second inspection step.

Losing focus or hiding the tab pauses active play. The arrow controls respond to fresh presses rather than held-key repeats. Reset cancels the prior frame callback, invalidates old-session work, prevents duplicate listeners and restores 12 bricks, three lives, zero score and the original ball/paddle state. Reset should return to awaiting Launch rather than immediately running an unrequested second loop.

Inspect the first launch

Step once from the initial awaiting-launch state: the center moves from (160, 190) to (164.5, 185.5), using 90 units per second on both axes. The step leaves the game paused so the next inspection is deliberate. Launch and Resume use one animation owner; pausing clears that callback before manual inspection.

The collision resolver checks swept circle contacts against brick faces and rounded corners, handles tied brick IDs in stable order, and ignores removed bricks. The paddle bounce requires downward travel across its top. A removed brick stays removed for the rest of that game. Reset rebuilds the original twelve-brick set, restores three lives and returns to awaiting Launch, rather than starting another loop.

Copy this prompt

Build an original ball-and-paddle game as a single HTML file. Put the canvas above clear Launch, Pause, Resume, Step and Reset controls, with separate paddle buttons and text for score, lives, remaining bricks and ball position.

Use a logical board 320 units wide and 240 high. The ball has radius 6, begins at (160, 190), and launches at velocity (90, -90) units per second. The paddle is 60 by 10, centered at x = 160 with its top at y = 210. Arrange twelve bricks in three rows of four. Their left coordinates are 20, 92, 164 and 236; their top coordinates are 30, 48 and 66. Each brick is 60 by 12.

Resolve the earliest swept circle contact with brick faces or corners. For simultaneous contacts, process unique brick IDs in stable order. Remove each brick once and award one point. Walls reverse outward motion at ball-center x = 6 or 314 and y = 6. A descending ball crossing the paddle top bounces upward.

A ball fully below the board loses one of three lives, resets the ball and paddle, and waits for Launch while keeping the score and remaining bricks. Zero bricks wins; zero lives loses. Both stop play.

Step advances 0.05 seconds while paused; the first step reaches (164.5, 185.5). Paddle buttons and focused arrow presses move 20 units; pointer movement maps through the canvas’s displayed size. Use one animation loop with elapsed updates capped at 50 milliseconds. Pause on focus loss, resume with a fresh timestamp, and make Reset return to the initial awaiting-launch state. Keep the canvas responsive and all controls readable.

Follow one hit in slow motion

Take the first paused step and compare (164.5, 185.5) with the initial center. Continue stepping until a brick disappears, then compare its ID with the remaining count and score. NOS can render the HTML game for this collision walkthrough. Reset before a new comparison so all twelve bricks and three lives begin in the same state.

Keep reading