Fix the fixed-timestep loop in a game engine

Review the AI's codeEasy12 min

Your task

Your engine's main loop adds each frame's time to an accumulator and runs physics in fixed steps until the accumulator is drained. On a slow laptop, physics took longer than a step, each frame queued more work than it could run, and the game froze: a death spiral. The fix clamps long frames, caps the steps per frame and drops any backlog the cap leaves behind.

An assistant wrote simulate_fixed_steps(frame_times_ms, fixed_dt_ms, max_frame_ms, max_steps_per_frame). It is in the editor. It has a bug. Find it and fix it.

Input and output:

  • frame_times_ms: each frame's measured time in milliseconds, in order.
  • fixed_dt_ms: the length of one physics step.
  • max_frame_ms: the most time one frame may add (0 or more). max_steps_per_frame: the most steps one frame may run.
  • Return the number of physics steps each frame runs.

Rules the tests check:

  • If fixed_dt_ms is 0 or less, return [].
  • The accumulator starts at 0. For each frame:
    1. A negative frame time counts as 0, and a frame time above max_frame_ms counts as max_frame_ms. Add it to the accumulator.
    2. While the accumulator is at least fixed_dt_ms and fewer than max_steps_per_frame steps have run this frame, run a step: subtract fixed_dt_ms.
    3. Then keep only the accumulator's remainder after dividing by fixed_dt_ms. Whole steps the cap left over are dropped, never carried into the next frame.
    4. Record the number of steps run.

Examples

simulate_fixed_steps(frame_times_ms: list[int], fixed_dt_ms: int, max_frame_ms: int, max_steps_per_frame: int) -> list[int]
Example 1
Inputsimulate_fixed_steps([16, 16, 16], 16, 250, 5)
Output[1, 1, 1]
Example 2
Inputsimulate_fixed_steps([1000], 16, 250, 5)
Output[5]