Create Swinging Pendulum Blades in Matter.js
This guide demonstrates how to build functional swinging pendulum blades in Matter.js to serve as corridor traps in 2D games. You will learn how to configure composite bodies, attach them to static pivots using constraints, sustain realistic swinging motion, and handle collision detection for hazardous game environments.
1. Setting Up the Pivot and Blade
A pendulum trap consists of two main physics elements: a fixed anchor point and a swinging body that acts as the arm and blade.
While you can link separate bodies for the arm and the blade, creating a single compound body or a dense rectangular body simplifies physics calculations and eliminates unwanted joint flexing.
const { Engine, Render, Runner, Bodies, Composite, Constraint, Body, Vector } = Matter;
// Initialize engine and renderer
const engine = Engine.create();
const world = engine.world;
const render = Render.create({
element: document.body,
engine: engine,
options: { width: 800, height: 600, wireframes: false }
});
Render.run(render);
Runner.run(Runner.create(), engine);2. Creating the Pendulum Assembly
Define the blade body, position it below a designated pivot
coordinate, and connect it using Matter.Constraint.
const pivotX = 400;
const pivotY = 100;
const armLength = 250;
// Create the blade (using a trapezoid or rectangle for the lethal edge)
const blade = Bodies.trapezoid(pivotX + armLength, pivotY, 60, 100, 0.5, {
density: 0.05,
frictionAir: 0.0005, // Low air resistance to sustain swing
restitution: 0.8,
render: { fillStyle: '#e74c3c' }
});
// Create the constraint connecting the blade to the fixed world point
const pendulumConstraint = Constraint.create({
pointA: { x: pivotX, y: pivotY },
bodyB: blade,
pointB: { x: 0, y: -armLength / 2 },
stiffness: 1,
length: armLength,
render: {
strokeStyle: '#bdc3c7',
lineWidth: 4
}
});
Composite.add(world, [blade, pendulumConstraint]);3. Sustaining the Pendulum Swing
Natural friction and gravity will eventually bring a standard
pendulum to a stop. To create an infinite hazard that sweeps across a
corridor, you can periodically apply torque or manually adjust the
body's velocity using the beforeUpdate engine event.
Matter.Events.on(engine, 'beforeUpdate', () => {
// Keep the pendulum swinging by checking its angle relative to the pivot
const currentAngle = blade.angle;
// Apply a subtle continuous driving force if velocity drops
if (Math.abs(blade.angularVelocity) < 0.02) {
const direction = Math.sin(currentAngle) > 0 ? -1 : 1;
Body.applyForce(blade, blade.position, {
x: direction * 0.05,
y: 0
});
}
});Alternatively, you can set blade.frictionAir = 0 to
preserve kinetic energy indefinitely, provided the simulation receives
an initial offset displacement when created.
4. Configuring Corridor Collision
Pendulum blades must interact with players while avoiding unwanted collisions with the ceiling or corridor walls:
- Collision Filtering: Assign
collisionFilter.categoryandmaskproperties to ensure the blade hits the player layer while passing through surrounding corridor structure bodies. - Sensors: If the blade should trigger death
animations or events without physically bouncing off player bodies, set
isSensor: trueon the blade body and listen for collision events usingMatter.Events.on(engine, 'collisionStart', handler).