Customize Delta Time in Matter.js Runner

Matter.js allows you to customize the delta time used by its physics simulation. You can control the time step either by configuring the delta and isFixed properties directly within the Matter.Runner module or by bypassing the runner completely to feed custom delta values directly into Matter.Engine.update. Customizing delta time is essential for achieving deterministic physics, implementing slow-motion or fast-forward effects, and ensuring stability across displays with varying refresh rates.

Configuring Delta Time in Matter.Runner

When using the built-in Matter.Runner, delta time is computed automatically using browser frame timestamps. However, you can enforce a fixed delta time by passing configuration options to Runner.create().

// Create a runner with a fixed 60 Hz delta time (16.666 ms)
const runner = Matter.Runner.create({
    isFixed: true,
    delta: 1000 / 60
});

// Start the runner with your engine
Matter.Runner.run(runner, engine);

Updating Delta at Runtime

You can modify the delta value dynamically on an active runner instance to change simulation speed on the fly:

// Double the simulation speed
runner.delta = (1000 / 60) * 2;

// Halve the simulation speed (slow motion)
runner.delta = (1000 / 60) * 0.5;

When changing the delta at runtime, ensure runner.isFixed remains true so the runner does not overwrite your custom value with the calculated elapsed time between frames.

Complete Control via Manual Engine Updates

If you need dynamic delta calculation based on your own game loop, you can omit Matter.Runner entirely and manually invoke Matter.Engine.update.

let lastTime = performance.now();

function gameLoop(currentTime) {
    // Calculate actual elapsed time in milliseconds
    let customDelta = currentTime - lastTime;
    lastTime = currentTime;

    // Cap the delta to prevent physics glitches during lag spikes
    customDelta = Math.min(customDelta, 100);

    // Apply custom delta directly to the engine
    Matter.Engine.update(engine, customDelta);

    requestAnimationFrame(gameLoop);
}

requestAnimationFrame(gameLoop);

Using manual engine updates provides the highest level of control, allowing you to implement fixed-timestep accumulators, pause states, and custom time-scaling logic without runner constraints.