Build a Rube Goldberg Machine in Matter.js

This article explains how to design and build a multi-stage Rube Goldberg machine using the Matter.js 2D physics engine. You will learn how to configure the physics environment, build diverse mechanical components such as domino runs, pendulums, seesaws, and release latches, and chain them together sequentially. The guide also covers crucial physics-tuning techniques—including mass ratios, collision filtering, constraints, and solver iterations—to ensure each mechanical trigger activates reliably.

Setting Up the Environment

To start, initialize the Matter.js engine, world, renderer, and runner. A Rube Goldberg machine relies on consistent gravity and deterministic physical updates to ensure chain reactions behave identically on each run.

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

const engine = Engine.create({
  positionIterations: 10,
  velocityIterations: 10
});

const render = Render.create({
  element: document.body,
  engine: engine,
  options: {
    width: 1200,
    height: 800,
    wireframes: false
  }
});

Render.run(render);
Runner.run(Runner.create(), engine);

Increasing positionIterations and velocityIterations prevents fast-moving objects from clipping through tracks or thin walls (tunneling).


Constructing Distinct Mechanical Actions

A compelling Rube Goldberg machine chains fundamentally different types of physics interactions. Below are the key mechanisms to build.

1. The Domino Run

Dominoes convert small lateral impulses into sequential tipping motions.

function createDominoes(startX, startY, count, spacing) {
  const dominoes = [];
  for (let i = 0; i < count; i++) {
    const domino = Bodies.rectangle(startX + i * spacing, startY, 10, 60, {
      friction: 0.4,
      restitution: 0.1,
      density: 0.002
    });
    dominoes.push(domino);
  }
  Composite.add(engine.world, dominoes);
}

Tip: Keep restitution (bounciness) low so dominoes don't bounce backward, and keep friction moderate so the base pivots rather than slips.

2. The Seesaw (First-Class Lever)

A seesaw transfers a downward impact on one side into an upward launch or trigger on the other.

const plank = Bodies.rectangle(400, 500, 200, 15, { density: 0.003 });
const fulcrum = Constraint.create({
  pointA: { x: 400, y: 500 },
  bodyB: plank,
  pointB: { x: 0, y: 0 },
  stiffness: 1,
  length: 0
});

Composite.add(engine.world, [plank, fulcrum]);

3. The Newton's Pendulum / Wrecking Ball

A pendulum gathers potential energy and releases kinetic energy upon collision to bridge large physical gaps.

const pendulumBob = Bodies.circle(600, 300, 25, { density: 0.05 });
const pendulumRope = Constraint.create({
  pointA: { x: 550, y: 150 },
  bodyB: pendulumBob,
  stiffness: 0.9,
  length: 150
});

Composite.add(engine.world, [pendulumBob, pendulumRope]);

4. Triggered Trapdoors and Dynamic Releases

Not all chains rely solely on raw momentum transfer. You can use Matter.js collision events to act as electronic or mechanical tripwires that dissolve constraints or drop gates.

const trapdoor = Bodies.rectangle(800, 400, 120, 10, { isStatic: true });
const sensor = Bodies.rectangle(750, 380, 20, 20, { 
  isSensor: true, 
  isStatic: true 
});

Composite.add(engine.world, [trapdoor, sensor]);

Events.on(engine, 'collisionStart', (event) => {
  event.pairs.forEach((pair) => {
    if (pair.bodyA === sensor || pair.bodyB === sensor) {
      // Release the trapdoor
      Matter.Body.setStatic(trapdoor, false);
    }
  });
});

Chaining Diverse Actions Sequentially

To successfully pass energy from one module to the next, layout and momentum budgeting are critical:

  1. Stage 1 (Initial Release): A heavy ball drops onto an inclined plane and accelerates toward the domino chain.
  2. Stage 2 (Momentum Transfer): The ball strikes the first domino. The final domino falls off its platform onto the high side of the seesaw.
  3. Stage 3 (Leverage): The falling domino drives the seesaw down, catapulting a light payload upward into the pendulum bob.
  4. Stage 4 (Swing & Trip): The pendulum swings forward, contacting the sensor block.
  5. Stage 5 (Trapdoor Finale): The sensor event removes the static property of the trapdoor, allowing a heavy weight to drop onto the final objective button.

Fine-Tuning for Deterministic Execution