After the game loop

Delta time

Direct answer: Multiply movement by the time since the last frame so an object travels the same distance on a 60Hz screen and a 120Hz screen.

What you need first

The game loop lesson. You should already know that requestAnimationFrame gives you a timestamp.

After this lesson

You can choose frame-based movement, time-based movement, or a fixed tick, and explain which one Snake uses.

A frame is not a unit of time

This line from the game-loop lesson is easy to copy and easy to regret:

x += 2; // two pixels every frame

On a 60Hz display that is about 120 pixels per second. On a 120Hz display it is about 240. The code did not change; the monitor did. Delta time is the gap between frames, usually in seconds:

let last = 0;
function loop(now) {
    const dt = Math.min(0.05, (now - last) / 1000);
    last = now;
    player.x += player.speed * dt; // speed is pixels per second
    requestAnimationFrame(loop);
}

Clamp dt. If the tab sleeps and wakes, one huge frame would teleport the player through walls.

When to use it

Use delta time for continuous motion: paddles, falling bodies, camera pans, particle fade. Do not use it as the only clock for a grid game. Snake should move one cell on a tick, not a fraction of a cell every frame.

Try it and check it

Both boxes travel at 180 pixels per second of intended speed. The top one adds a fixed amount every frame. The bottom one multiplies by dt. Change the fake refresh rate. Only the bottom box should keep the same crossing time.

Snake uses a fixed tick, then still measures time

The beginner Snake project calls setInterval(tick, 130). That is a fixed tick: one cell, then wait. The shipped Snake remake is more careful. It still moves on a grid, but the render loop uses requestAnimationFrame and an accumulator:

const dt = Math.min(48, ts - lastTs);
acc += dt;
while (acc >= stepMs) {
    acc -= stepMs;
    step(); // one cell
}

That is why Blitz mode can subtract seconds from a timer without making the snake slide between cells. Time is measured; movement stays discrete.

Common mistake

Using raw now - last after a background tab, or mixing x += speed in one object with x += speed * dt in another. Pick one clock per system.

Real game connection

Breakout’s paddle and ball want time-based or at least consistent motion. Snake wants a tick. 2048 does not animate the rules at all: a swipe either merges the grid or it does not. Choose the clock that matches the rule, not the clock that sounds more advanced.

Compatibility: requestAnimationFrame timestamps work in current Chrome, Firefox, Safari, and Edge. The demo fakes refresh rate in software so you can see the difference without swapping monitors.

Source and update: Reviewed against MDN Web Docs for requestAnimationFrame. Updated 2026-08-13.

Next actions: Fixed timestep · Input controls · Build Snake