Back to Blog
Tools

Breakout Game Development: Canvas API, Ball Physics, and Collision Detection Explained

Breakout's deceptively simple mechanics hide a rich set of programming problems: smooth animation, real-time physics, per-brick collision detection, and difficulty progression all within a browser canvas.

Breakout was designed by Steve Wozniak and Steve Jobs at Atari in 1976. The brief: a single-player version of Pong where the opponent is a wall of bricks that the ball destroys. It became one of the foundational games of the arcade era and has been reimplemented in virtually every programming language as a learning exercise. For browser development, Breakout is an ideal Canvas API project: it requires animation loops, real-time physics, collision detection, input handling, score management, and visual rendering — a complete miniature game engine in a few hundred lines of JavaScript.

Breakout game canvas development

Canvas API Fundamentals for Game Development

The HTML Canvas API provides a 2D drawing surface controlled entirely through JavaScript. The API is imperative — you draw by calling methods on a 2D rendering context, and the canvas doesn't maintain a model of what's been drawn; it's just pixels. This means every frame, you must redraw the entire scene: clear the canvas, then draw each game element in the correct order.

The rendering context is obtained with const ctx = canvas.getContext('2d'). Key drawing operations: ctx.fillRect(x, y, width, height) draws a filled rectangle; ctx.clearRect(0, 0, canvas.width, canvas.height) clears the entire canvas; ctx.beginPath(), ctx.arc(x, y, radius, 0, Math.PI * 2), ctx.fill() draws a filled circle. Setting ctx.fillStyle before drawing operations controls color.

The game loop uses requestAnimationFrame for smooth, battery-efficient animation. The callback receives a timestamp in milliseconds that can be used to compute delta time — the time elapsed since the last frame. Delta-time-based physics (multiplying velocities by delta time before adding to position) ensures the game runs at consistent speed regardless of frame rate variations, which is essential for fair gameplay on different devices.

Ball Physics and Movement

The ball is defined by its position (x, y), its velocity vector (dx, dy), and its radius. Each frame, the position is updated by adding the velocity: x += dx, y += dy. The velocity components represent speed in pixels per frame (or pixels per second with delta time scaling). A ball moving at 45 degrees would have equal magnitude dx and dy.

Wall bouncing is implemented by negating the appropriate velocity component when the ball reaches a boundary. Left and right walls negate dx. The top wall (ceiling) negates dy. The bottom of the screen is the game-over condition — no bounce. This simple negation model produces realistic-feeling reflections for axis-aligned surfaces.

Speed progression is a critical difficulty mechanic. Starting too fast makes the game unplayable; staying at the same speed makes later levels boring. Common approaches: increase ball speed by a small percentage each time a row of bricks is cleared, or increase speed with each brick hit up to a maximum. A small speed increase per cleared brick feels natural and gradual; a large increase per level creates a clear difficulty step between levels.

Paddle Collision

The paddle is a rectangle controlled by mouse movement or arrow keys. Collision between the ball and the paddle requires checking: the ball's y position is at the paddle's y level, and the ball's x position is within the paddle's horizontal extent. When both conditions are true, the ball bounces upward (dy negated to negative).

Simple paddle collision (reflect at any point) produces predictable, boring bounces. A more interesting mechanic: the bounce angle depends on where the ball hits the paddle. Hitting near the center produces a steep bounce close to vertical; hitting near the edges produces a shallower, more horizontal bounce. This gives the player directional control and is implemented by computing the ball's offset from the paddle's center as a fraction of the paddle's half-width, then setting dx and dy as sine and cosine of the resulting angle.

Ensuring the ball cannot pass through the paddle at high speeds (tunneling) requires positioning the ball to the paddle's top surface whenever a collision is detected, in addition to negating dy. Without this correction, a fast ball can overlap the paddle's interior by several pixels before collision is detected, causing the ball to be trapped inside the paddle and bouncing chaotically.

Brick Grid and Collision

The brick grid is a 2D array where each element is a brick object with an active boolean (whether the brick still exists), a color, and possibly a hit-point value (for multi-hit bricks). The grid is drawn by iterating the array and drawing rectangles for all active bricks. When a brick is hit, its active property is set to false, making it invisible and non-collidable in subsequent frames.

Brick collision detection: for each active brick, check if the ball's bounding box intersects the brick's bounding box. The intersection test: check if the ball's center plus radius overlaps the brick's rectangular area. A more precise test uses the signed distance from the ball center to the nearest point on the brick rectangle — if this distance is less than the ball's radius, a collision has occurred.

Determining which face of the brick was hit — top, bottom, left, or right — determines how to reflect the ball. The simplest approach: if the ball approached primarily from above or below (|dy| is larger), negate dy; if primarily from the side (|dx| is larger), negate dx. This approximation works well for most collisions. Edge cases (corner hits) can produce unexpected behaviour in any simple approximation; perfect corner handling requires computing the exact collision normal, which is substantially more complex.

Collision detection physics diagram

Power-Ups and Game Progression

Classic Breakout variants include power-ups that fall from destroyed bricks and activate when caught by the paddle. Common power-ups: paddle width expansion (makes the game easier), multi-ball (splits the ball into three, dramatically increasing brick-clearing speed but requiring coordination), catch (ball sticks to paddle until released, giving positional control), laser (paddle shoots bullets to destroy bricks directly). Power-ups add strategic depth and visual variety that keeps the game engaging across multiple levels.

Level progression in Breakout is typically implemented as a sequence of brick layouts. Level 1 uses a simple rectangular grid. Later levels use sparser patterns, patterns with gaps that require precise shots to reach remaining bricks, and higher proportions of harder bricks. Designing these layouts is essentially level design — a creative process that determines the game's difficulty curve and aesthetic variety.

Our Breakout Implementation

Our browser-based Breakout features five rows of coloured bricks, smooth mouse-controlled paddle movement, progressive ball speed increases, a lives system (three lives per game), score display, and high score persistence in localStorage. The entire implementation is pure JavaScript with Canvas API rendering — no game engine, no libraries, no assets beyond the page code. It demonstrates that compelling real-time interactive experiences are achievable in a browser with only the Web APIs built into every modern browser.

More Articles