Limit Maximum Angular Velocity in Matter.js
This article explains how to restrict the maximum angular velocity of
a rigid body in Matter.js to prevent objects from spinning
uncontrollably. Matter.js does not feature a built-in property to
hard-cap rotational speed automatically, but you can achieve this by
listening to the physics engine's update cycle and clamping the velocity
value manually. Below is the direct method to implement this using the
beforeUpdate engine event.
Clamping Angular
Velocity with beforeUpdate
The standard approach to capping rotational speed is to evaluate the
body's angularVelocity on every tick before the physics
calculations are resolved. If the absolute value of the angular velocity
exceeds your designated limit, you clamp it back to the maximum allowed
threshold using Matter.Body.setAngularVelocity.
Here is the complete implementation:
const { Engine, Render, Runner, Bodies, Composite, Events, Body } = Matter;
// Create an engine and a world
const engine = Engine.create();
const world = engine.world;
// Create a body
const box = Bodies.rectangle(400, 200, 80, 80);
Composite.add(world, box);
// Define your maximum angular velocity (in radians per step)
const MAX_ANGULAR_VELOCITY = 0.1;
// Intercept the engine before each physics update
Events.on(engine, 'beforeUpdate', () => {
const currentAngularVelocity = box.angularVelocity;
if (Math.abs(currentAngularVelocity) > MAX_ANGULAR_VELOCITY) {
// Preserve the direction of rotation while capping the magnitude
const clampedVelocity = Math.sign(currentAngularVelocity) * MAX_ANGULAR_VELOCITY;
Body.setAngularVelocity(box, clampedVelocity);
}
});Applying the Limit to All Bodies in a Scene
If your simulation requires all dynamic bodies to adhere to an angular speed limit, you can iterate over all composite bodies within the same event listener:
Events.on(engine, 'beforeUpdate', () => {
const bodies = Composite.allBodies(engine.world);
const MAX_ANGULAR_VELOCITY = 0.15;
for (let i = 0; i < bodies.length; i++) {
const body = bodies[i];
// Skip static bodies
if (body.isStatic) continue;
if (Math.abs(body.angularVelocity) > MAX_ANGULAR_VELOCITY) {
Body.setAngularVelocity(
body,
Math.sign(body.angularVelocity) * MAX_ANGULAR_VELOCITY
);
}
}
});Alternative: Adjusting
frictionAir
If a hard clamp causes unnatural visual snapping in your simulation,
an alternative is to increase the frictionAir property on
the body. While frictionAir does not establish a strict
maximum limit, it introduces rotational drag that naturally prevents
bodies from sustaining extreme rotational speeds:
const box = Bodies.rectangle(400, 200, 80, 80, {
frictionAir: 0.05 // Default is 0.01
});For strict physics boundaries, combining the
beforeUpdate clamping logic with appropriate air friction
provides both stability and realistic movement.