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
| Architecture | Update Frequency | Physics Determinism | Edge Case Handling |
|---|---|---|---|
| Naive Variable Delta | Tied 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 Timestep | Fixed physics + Alpha render blending | Perfect Smoothness & Determinism | Renders 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.
