Constant Angular Velocity in Matter.js
This article explains how to create a continuous motor effect in Matter.js to maintain a target angular velocity. Because the Matter.js physics engine lacks a built-in motorized constraint, developers must apply manual intervention. You will learn the two primary methods to achieve continuous rotation: directly enforcing angular velocity every simulation tick for an unstoppable motor, and calculating dynamic torque for realistic physical interactions.
Method 1: Directly Setting Angular Velocity
The most reliable way to maintain a strictly constant rotational
speed is to override the body’s angular velocity on every frame using
the engine's beforeUpdate event. This prevents air
resistance (frictionAir) and collisions from slowing the
body down.
const { Engine, Events, Body } = Matter;
const engine = Engine.create();
const targetAngularVelocity = 0.05; // Radians per tick
// Target body to act as a motor
const motorBody = Bodies.rectangle(400, 300, 200, 20, {
frictionAir: 0 // Optional: minimize damping
});
// Update the body before every physics calculation
Events.on(engine, 'beforeUpdate', () => {
Body.setAngularVelocity(motorBody, targetAngularVelocity);
});Why This Works
Matter.js applies damping and constraint resolution during each tick.
By setting the velocity inside beforeUpdate, you ensure
that the body enters the collision and integration phases with the exact
desired speed, acting as an infinitely strong motor.
Method 2: Applying Dynamic Proportional Torque
If you want a realistic motor that reacts to loads—slowing down when blocked and exerting torque to catch up—use a proportional control loop (a simple P-controller) to assign torque each frame.
const targetAngularVelocity = 0.05; // Desired speed (rad/tick)
const motorStrength = 0.1; // Proportional gain (Kp)
const maxTorque = 0.05; // Maximum torque limit
Events.on(engine, 'beforeUpdate', () => {
// Calculate the difference between target and current speed
const velocityError = targetAngularVelocity - motorBody.angularVelocity;
// Calculate torque required to correct the error
let appliedTorque = velocityError * motorStrength;
// Clamp the torque to a realistic maximum limit
appliedTorque = Math.max(-maxTorque, Math.min(maxTorque, appliedTorque));
// Apply the torque directly to the body
motorBody.torque = appliedTorque;
});When to Use Torque Over Velocity
- Physical Resistance: If the rotating body hits a heavy object, torque allows the motor to stall or struggle naturally rather than launching objects with infinite impulse.
- Realistic Acceleration: The body smoothly accelerates from rest up to the target speed instead of instantly snapping to the target velocity.
Important Configuration Settings
To ensure predictable rotational behavior, adjust the following properties on your rotating body:
frictionAir: Defaults to0.01. Set this to0if you want zero environmental resistance, or keep it low to simulate friction within the motor's axle.inertia: If you use Method 2 (Torque), increasing the body's mass or inertia requires a correspondingly highermotorStrengthto achieve the target speed within a reasonable timeframe.- Pivots with Constraints: If the body needs to stay
in place while spinning, anchor its center using a
Constraint:
const constraint = Matter.Constraint.create({
pointA: { x: 400, y: 300 },
bodyB: motorBody,
pointB: { x: 0, y: 0 },
stiffness: 1,
length: 0
});
Matter.World.add(engine.world, [motorBody, constraint]);