moves / game dev / fixed timestep loop

Fixed-timestep game loop

Run physics in fixed steps and render as often as the screen allows. An accumulator carries leftover time between frames, so a 60 Hz and a 144 Hz monitor simulate the same game. Clamp the frame time so a backgrounded tab doesn't try to catch up on minutes of updates. Phaser, Godot, and Unity do this for you; write it yourself when you're on plain Canvas or a renderer like PixiJS.

#game-loop#requestanimationframe#physics#timing
ts
const STEP = 1 / 60; // seconds per simulation tick
let accumulator = 0;
let last = performance.now();

function frame(now: number) {
  // Clamp so a backgrounded tab doesn't dump seconds of catch-up at once
  accumulator += Math.min((now - last) / 1000, 0.25);
  last = now;

  while (accumulator >= STEP) {
    update(STEP); // physics + game logic, always the same dt
    accumulator -= STEP;
  }

  render(accumulator / STEP); // 0..1: blend between last two states
  requestAnimationFrame(frame);
}

requestAnimationFrame(frame);

Related

WWADD — Moves. Stacks. Judgment calls.

FREE REFERENCE · NO LOGIN · NO TRACKING