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:
- Engine: Manages the simulation state and updates.
- World: Contains all bodies and constraints within the simulation.
- Bodies: Creates geometric shapes such as rectangles, circles, and polygons.
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:
- Advance the physics simulation using
Engine.update(engine). - Extract the position (
body.position) and angle (body.angle) of each Matter.js body. - Use p5's
translate()androtate()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:
- Check if a body's
position.yexceeds the canvas boundaries. - Remove it from the physics world using
World.remove(world, body). - Remove it from your rendering array using
array.splice().