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