Accumulate elapsed time and run bounded updates
In each animation callback, add elapsed time to an accumulator. While the accumulator contains at least one step, update physics by a constant interval such as 1/60 of a second and subtract that interval. Then render the latest state. Set a maximum number of catch-up steps per frame; otherwise a long pause can cause a large backlog that consumes more time and deepens the delay. Decide explicitly whether excess time is dropped, capped, or handled by another recovery rule.
Keep units consistent. If velocity is measured in world units per second, multiply it by the fixed step inside each simulation update. Do not multiply the same velocity by the frame's full elapsed time and also execute several fixed updates, or movement will be counted twice.
Handle input and rendering at their own boundaries
Sample held input for each simulation step or queue one-shot actions until a step consumes them. If a key press happens between two frames, make sure it is not lost before the next update. Rendering can interpolate between physics states, while collision and scoring use simulation state. MDN describes requestAnimationFrame as a one-shot callback scheduled before repaint and advises using its timestamp to calculate progress; an accumulator uses that timestamp to keep updates fixed.
Test the limits of the loop
Compare the same short movement and collision across ordinary frames, a simulated slow frame, and a longer pause. Verify that a player does not tunnel through a thin wall, gain extra speed after a stall, or trigger a collision several times during catch-up. Test pause and hidden-tab return according to your intended rule. If the fixed-step loop makes the simulation stable but a collision still misses at high speed, use a collision method suited to the motion rather than raising the render frequency.
Questions about fixed timestep game physics
Does a fixed timestep guarantee deterministic physics?
No. It makes the simulation interval consistent, but input timing, math, and collision ordering can still produce variation. Control those separately for tests that require replay.
Why cap catch-up updates after a frame stall?
Without a bound, catching up can monopolize later frames and worsen the delay. Choose and test a recovery policy that fits the game, including whether simulated time may be discarded.