How to Create Conveyor Belts in Matter.js
Simulating conveyor belt mechanics in Matter.js requires applying a continuous tangential force or velocity modification to bodies in contact with the belt surface. Because Matter.js lacks a native "surface velocity" property like some other 2D physics engines, this behavior is achieved by detecting collisions between dynamic objects and the conveyor body using collision events, calculating the surface tangent vector, and applying directional force to the interacting bodies on each physics step.
Creating the Conveyor Body
Start by defining the conveyor belt as a static body within your Matter.js world. Set its friction high enough to prevent contacting objects from sliding freely without interacting with the belt surface.
const conveyorBelt = Matter.Bodies.rectangle(400, 500, 300, 20, {
isStatic: true,
friction: 0.8,
angle: 0 // Can be angled to support inclined belts
});
Matter.Composite.add(engine.world, conveyorBelt);Detecting Active Collisions
To exert a continuous tangential force, listen to the
collisionActive event emitted by the
Matter.Engine. This event fires on every tick for any
bodies that are currently touching, allowing you to filter for
collisions involving your conveyor belt.
Matter.Events.on(engine, 'collisionActive', (event) => {
const pairs = event.pairs;
for (let i = 0; i < pairs.length; i++) {
const { bodyA, bodyB } = pairs[i];
if (bodyA === conveyorBelt || bodyB === conveyorBelt) {
const movingObject = bodyA === conveyorBelt ? bodyB : bodyA;
if (!movingObject.isStatic) {
applyConveyorForce(conveyorBelt, movingObject);
}
}
}
});Calculating and Applying Tangential Force
The tangential force must align with the orientation of the conveyor
belt. Use the conveyor body's angle property to compute the
unit tangent vector, scale it by your desired force magnitude, and apply
it to the contacting body using Matter.Body.applyForce.
function applyConveyorForce(belt, targetBody) {
const beltSpeed = 0.005; // Force magnitude scaled to object mass
// Calculate the tangent vector parallel to the belt surface
const tangentX = Math.cos(belt.angle);
const tangentY = Math.sin(belt.angle);
// Apply the tangential force directly at the center of mass
Matter.Body.applyForce(targetBody, targetBody.position, {
x: tangentX * beltSpeed * targetBody.mass,
y: tangentY * beltSpeed * targetBody.mass
});
}Multiplying the force by targetBody.mass ensures that
objects of differing masses accelerate along the conveyor belt at a
consistent rate.
Alternative: Velocity Clamping for Consistent Belt Speed
If using Body.applyForce results in objects constantly
accelerating beyond the intended belt speed, you can instead adjust the
body's velocity directly or clamp it along the tangent axis:
function applyConveyorVelocity(belt, targetBody) {
const targetSpeed = 3; // Desired belt speed in pixels/step
const tangentX = Math.cos(belt.angle);
const tangentY = Math.sin(belt.angle);
// Project current velocity onto the tangent vector
const currentTangentSpeed = (targetBody.velocity.x * tangentX) + (targetBody.velocity.y * tangentY);
if (currentTangentSpeed < targetSpeed) {
// Accelerate object toward target speed along the surface
const speedDifference = targetSpeed - currentTangentSpeed;
const forceMagnitude = Math.min(speedDifference * 0.01, 0.05);
Matter.Body.applyForce(targetBody, targetBody.position, {
x: tangentX * forceMagnitude * targetBody.mass,
y: tangentY * forceMagnitude * targetBody.mass
});
}
}This velocity-aware approach mimics real-world conveyor systems by accelerating bodies until they match the linear speed of the belt, preventing runaway acceleration while maintaining stable friction-based physics interactions.