The Game Loop
Every game has a heartbeat. It's an infinite loop that runs 60 times every second, updating the world and drawing it to the screen.
Why do we need a loop?
Unlike a static website, a game is a dynamic simulation. Characters move, physics calculations happen, and inputs are processed constantly. To achieve this, we need a function that runs repeatedly.
In modern HTML5 development, the specialized function for this is requestAnimationFrame.
The Anatomy of a Frame
Each iteration of the loop (a "frame") typically performs three steps:
- Update: Calculate new positions, check collisions, process input.
- Clear: Wipe the canvas clean from the previous frame.
- Draw: Render everything in their new positions.
See it on this page
The box below updates, clears, and draws every animation frame. Change speed, then open the Playground if you want to edit the source.
Open in Playground
The Code
Here is the minimal template for any HTML5 Canvas game:
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
let x = 0;
function gameLoop() {
// 1. UPDATE state
x += 2; // Move logic
if (x > canvas.width) x = 0;
// 2. CLEAR canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 3. DRAW everything
ctx.fillStyle = '#4ade80';
ctx.fillRect(x, 100, 50, 50);
// 4. REPEAT
requestAnimationFrame(gameLoop);
}
// Start the engine!
gameLoop();
Why not setInterval?
You might be tempted to use setInterval(loop, 16). Don't do it!
requestAnimationFrame is superior because:
- It pauses when the tab is inactive (saving battery).
- It syncs with your screen's refresh rate (usually 60Hz) for smoother motion.
- It provides a timestamp for precise delta-time calculations.
Why the next lesson is input, not collision
The loop above moves a box by a fixed amount every frame. That is enough to see drawing work. Before you detect hits, learn to record keys as state. Collision examples need that input. After input and collision, game state will show why a pause flag belongs outside the drawing code.
One caution already visible here: x += 2 is frame-rate dependent. A 120Hz screen advances twice as far. When you need the same speed everywhere, continue to the delta time lesson. The beginner Snake project stays on a fixed tick instead, which is the simpler rule for a grid game.
Continue learning: Delta time · Input controls · Build Snake
Before you continue
Direct answer: A game loop repeatedly updates state and then draws the current state. In browsers, requestAnimationFrame is the normal starting point.
What you need first
A canvas and a small object with position data.
After this lesson
You can explain the idea, change the supplied example, and choose the next related lesson.
When to use it
Use requestAnimationFrame for animation tied to painting. Do not assume every screen refreshes at the same speed.
Common mistake
Moving an object by a fixed amount every frame without considering elapsed time.
Try it and check it
This lesson includes its runnable example or code experiment above. Change one value, run it again, and confirm the visible result changes before moving on.
Real game connection
See the loop put to use in the Snake project.
Compatibility: Test in a current Chrome, Firefox, Safari, or Edge browser. Canvas and standard input work broadly in current browsers; audio still needs a user action.
Source and update
Reviewed against MDN Web Docs. Updated 2026-07-14. This page does not claim performance results beyond the local example check.