How to Integrate Matter.js with p5.js

Integrating Matter.js with p5.js combines the advanced 2D physics simulation of Matter.js with the intuitive rendering and creative coding capabilities of p5.js. Because Matter.js calculates rigid-body dynamics behind the scenes, you can bypass its default renderer and use p5.js to visually draw shapes according to those physical calculations. This guide covers the basic setup, decoupling the Matter.js renderer, synchronizing physics updates with the p5.js animation loop, and rendering dynamic bodies onto the canvas.

1. Include the Libraries

To begin, include both the p5.js and Matter.js libraries in your HTML file via CDN:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Matter.js and p5.js</title>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.9.0/p5.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.19.0/matter.min.js"></script>
  <script src="sketch.js"></script>
</head>
<body>
</body>
</html>

2. Core Concepts of Integration

Matter.js is modular. When combining it with p5.js, you only need three core modules:

You will omit Matter.Render and Matter.Runner, as p5.js will manage the rendering pipeline and frame updates using createCanvas() and the draw() loop.

3. Setting Up the Engine and Canvas

In your JavaScript file (e.g., sketch.js), create aliases for Matter.js modules and initialize the engine inside the setup() function:

const { Engine, World, Bodies } = Matter;

let engine;
let world;
let boxes = [];
let ground;

function setup() {
  createCanvas(800, 600);

  // Initialize the engine and extract the world
  engine = Engine.create();
  world = engine.world;

  // Create a static ground body
  ground = Bodies.rectangle(width / 2, height - 20, width, 40, { isStatic: true });
  World.add(world, ground);
}

4. Updating and Drawing the Physics Bodies

Inside the p5.js draw() loop:

  1. Advance the physics simulation using Engine.update(engine).
  2. Extract the position (body.position) and angle (body.angle) of each Matter.js body.
  3. Use p5's translate() and rotate() matrix transformations to draw shapes at the calculated coordinates.
function draw() {
  background(30);

  // Advance the physics engine by one step
  Engine.update(engine);

  // Draw the static ground
  rectMode(CENTER);
  fill(120);
  noStroke();
  rect(ground.position.x, ground.position.y, width, 40);

  // Draw all dynamic bodies
  fill(255);
  for (let i = 0; i < boxes.length; i++) {
    let b = boxes[i];
    push();
    translate(b.position.x, b.position.y);
    rotate(b.angle);
    rect(0, 0, 40, 40);
    pop();
  }
}

5. Adding User Interaction

Because p5.js controls the event loop, you can spawn new physics bodies when the user interacts with the canvas, such as clicking or dragging:

function mouseDragged() {
  // Create a dynamic box at the mouse coordinates
  let box = Bodies.rectangle(mouseX, mouseY, 40, 40, {
    restitution: 0.6, // Bounciness
    friction: 0.1
  });

  boxes.push(box);
  World.add(world, box);
}

6. Memory Management

Bodies that fall outside the canvas bounds remain in memory and continue to be calculated by the physics engine. To maintain performance: