Game Engine Architecture

HTML5 Canvas 2D Game Loop Architecture: Delta Time, Fixed Timesteps & Interpolation

The foundation of any real-time interactive game or simulation is its game loop. Relying naively on raw requestAnimationFrame with variable delta time introduces non-deterministic physics glitches, tunneling through collision walls on frame drops, and erratic gameplay across different display refresh rates (60Hz vs 144Hz). Engineering a deterministic game loop requires decoupled fixed physics updates paired with state interpolation.

1. Variable Delta Time vs Fixed Timestep Physics

ArchitectureUpdate FrequencyPhysics DeterminismEdge Case Handling
Naive Variable DeltaTied directly to RAF (~16.6ms / 60Hz)Non-deterministic (Physics breaks on lag spikes)Objects tunnel through collision barriers during frame drops.
Fixed Timestep (Accumulator)Decoupled constant tick (e.g. 10ms / 100Hz)100% Deterministic (Identical trajectory across devices)Accumulates leftover frame time; runs multiple sub-ticks if lag occurs.
Interpolated Fixed TimestepFixed physics + Alpha render blendingPerfect Smoothness & DeterminismRenders smooth visual position between previous and current physics state.

2. The Deterministic Accumulator Game Loop

// Production-Grade Deterministic Game Loop with Render Interpolation
const FIXED_STEP = 1000 / 60; // 60 updates per second (16.66ms)
let lastTime = performance.now();
let accumulator = 0;

function gameLoop(currentTime) {
  let frameTime = currentTime - lastTime;
  if (frameTime > 250) frameTime = 250; // Prevent spiral of death on tab switch
  lastTime = currentTime;
  accumulator += frameTime;

  while (accumulator >= FIXED_STEP) {
    previousState.copy(currentState);
    physicsUpdate(currentState, FIXED_STEP);
    accumulator -= FIXED_STEP;
  }

  const alpha = accumulator / FIXED_STEP;
  renderInterpolated(previousState, currentState, alpha);
  requestAnimationFrame(gameLoop);
}
requestAnimationFrame(gameLoop);

âš¡ Performance Invariant

Never perform heavy DOM operations or dynamic heap allocations inside the while (accumulator >= FIXED_STEP) loop. Reuse existing vector and matrix objects to prevent garbage collection pauses from stalling frame rendering.

Robert Baindourov

Written by Robert Baindourov & CodeInFlash Interactive Systems Council

Senior interactive systems architect and graphics engineer specializing in HTML5 Canvas 2D game loops, WebGL shader pipelines, WebAssembly physics integration, and digital game preservation.

Need Custom Game Architecture or Graphics Advisory?

Collaborate with Codeinflash engineers to build resilient, high-speed 60 FPS interactive systems.

Book Consultation