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
});