How to Limit Maximum Velocity in Matter.js

Limiting the maximum velocity of a body in Matter.js requires clamping the body's velocity vector during the physics update cycle, as the engine does not provide a built-in maxVelocity property. By listening to the engine's beforeUpdate event, you can inspect the current speed of a body and rescale its velocity components if they exceed your defined threshold. This guide explains how to implement this clamp for linear velocity and angular velocity.

Clamping Linear Velocity

To limit how fast a body can move, calculate the magnitude of its velocity vector on each physics tick. If the magnitude is greater than your maximum allowed speed, scale the vector down to match the maximum limit.

Here is the implementation using the beforeUpdate event:

const { Engine, Events, Body, Vector } = Matter;

const engine = Engine.create();
const maxSpeed = 10; // Maximum units per tick

Events.on(engine, 'beforeUpdate', () => {
    // Replace 'myBody' with your target body reference
    const currentSpeed = Vector.magnitude(myBody.velocity);

    if (currentSpeed > maxSpeed) {
        // Calculate the scale factor to reduce velocity to maxSpeed
        const scaleFactor = maxSpeed / currentSpeed;

        Body.setVelocity(myBody, {
            x: myBody.velocity.x * scaleFactor,
            y: myBody.velocity.y * scaleFactor
        });
    }
});

Limiting Velocity for Multiple Bodies

If you need to limit the speed across several bodies, you can tag them with a custom property or iterate through a specific array of bodies within the same event listener.

Events.on(engine, 'beforeUpdate', () => {
    const bodies = Composite.allBodies(engine.world);

    bodies.forEach((body) => {
        if (body.maxSpeed) {
            const currentSpeed = Vector.magnitude(body.velocity);

            if (currentSpeed > body.maxSpeed) {
                const scaleFactor = body.maxSpeed / currentSpeed;
                Body.setVelocity(body, {
                    x: body.velocity.x * scaleFactor,
                    y: body.velocity.y * scaleFactor
                });
            }
        }
    });
});

To apply this, attach the maxSpeed property directly to any body you instantiate:

const myBody = Bodies.circle(100, 100, 20);
myBody.maxSpeed = 8;

Limiting Angular Velocity (Rotation Speed)

A body subjected to high torque may spin uncontrollably. You can cap angularVelocity in radians per tick within the same update loop using standard number clamping:

const maxAngularVelocity = 0.1; // Maximum rotation speed in radians per tick

Events.on(engine, 'beforeUpdate', () => {
    if (Math.abs(myBody.angularVelocity) > maxAngularVelocity) {
        const clampedRotation = Math.sign(myBody.angularVelocity) * maxAngularVelocity;
        Body.setAngularVelocity(myBody, clampedRotation);
    }
});

Alternative: Using Air Friction

If you prefer a natural deceleration rather than an abrupt speed ceiling, increase the body's frictionAir property. A higher frictionAir value applies progressive drag to the body, preventing it from reaching extreme speeds under continuous forces.

const myBody = Bodies.rectangle(200, 200, 50, 50, {
    frictionAir: 0.05 // Default is typically 0.01
});