Create a Wrecking Ball Using Matter.js Composites

This article explains how to build a dynamic, swinging wrecking ball simulation using the Matter.js 2D physics engine. You will learn how to use the Composites module to generate a flexible chain, attach a high-density circular body to act as the wrecking ball, anchor the chain to a fixed point in the scene, and integrate everything into a runnable physics world.

1. Initialize Matter.js Modules

Start by destructuring the core modules from the Matter namespace. You will need the Engine, Render, Runner, Bodies, Composite, Composites, and Constraint modules.

const {
    Engine,
    Render,
    Runner,
    Bodies,
    Composite,
    Composites,
    Constraint
} = Matter;

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. Create the Chain Using Composites

The rope or chain is formed by generating a vertical stack of small rectangles and linking them together using Composites.chain.

const startX = 400;
const startY = 100;
const links = 8;
const linkWidth = 20;
const linkHeight = 25;

// Generate a stack of chain links
const rope = Composites.stack(startX, startY, 1, links, 0, 10, function(x, y) {
    return Bodies.rectangle(x, y, linkWidth, linkHeight, {
        collisionFilter: { group: Matter.Body.nextGroup(true) },
        chamfer: 5
    });
});

// Connect the links using constraints
Composites.chain(rope, 0.5, -0.5, 0.5, 0.5, {
    stiffness: 0.9,
    length: 5,
    render: { type: 'line' }
});

3. Create and Attach the Wrecking Ball

Create a large, dense circle to act as the wrecking ball. Then, attach it to the last body in the rope composite using a Constraint.

const lastLink = rope.bodies[rope.bodies.length - 1];

// Create a heavy ball
const ball = Bodies.circle(startX, startY + (links * linkHeight) + 40, 40, {
    density: 0.05, // High density makes it act like a heavy weight
    render: { fillStyle: '#333333' }
});

// Connect the ball to the bottom link
const ballConstraint = Constraint.create({
    bodyA: lastLink,
    pointA: { x: 0, y: linkHeight / 2 },
    bodyB: ball,
    pointB: { x: 0, y: 0 },
    stiffness: 0.9,
    length: 0
});

4. Anchor the Chain to the World

To prevent the entire chain from falling due to gravity, pin the first body in the chain to a fixed coordinate.

const firstLink = rope.bodies[0];

const anchor = Constraint.create({
    pointA: { x: startX, y: startY },
    bodyB: firstLink,
    pointB: { x: 0, y: -linkHeight / 2 },
    stiffness: 1
});

5. Add Everything to the World

Add the rope composite, the wrecking ball, and the anchoring constraints to the physics world. You can also add target objects to test the wrecking ball's impact.

// Add wrecking ball components to the world
Composite.add(world, [rope, ball, ballConstraint, anchor]);

// Optional: Add a stack of boxes to knock down
const stack = Composites.stack(550, 300, 5, 10, 0, 0, function(x, y) {
    return Bodies.rectangle(x, y, 30, 30);
});

// Add ground
const ground = Bodies.rectangle(400, 590, 810, 20, { isStatic: true });

Composite.add(world, [stack, ground]);

Once loaded, the wrecking ball will naturally swing toward targets or react dynamically when mouse interaction or external velocity is applied.