How Matter.js Handles 2D Physics Simulation
Matter.js is an open-source 2D physics engine built for the web using JavaScript. It powers browser games and interactive visualizations by simulating realistic mechanical behaviors such as gravity, collisions, and friction. This article examines how Matter.js functions under the hood, exploring its core architecture, rigid body dynamics, two-phase collision detection system, constraint solving, and simulation loop execution.
The Modular Architecture
Matter.js relies on a decoupled, modular architecture where computation and rendering are separated:
- Engine: The brain of the simulation. It manages the update cycle, applies forces, and controls state progression.
- World: A specialized container (an extension of the
Compositemodule) that holds all active bodies, constraints, and composite assemblies. - Runner: The timing coordinator that updates the
Engineat fixed or variable intervals, typically synchronizing with the browser'srequestAnimationFrame. - Render: An optional canvas-based renderer primarily used for debugging and prototyping. Because rendering is completely decoupled, developers can easily swap it out for Pixi.js, Three.js, or direct DOM manipulation.
Rigid Body Dynamics
Matter.js simulates rigid bodies—objects that do not deform when forces are applied. Bodies can be standard primitives (rectangles, circles) or arbitrary convex polygons.
Each body is defined by mechanical properties:
- Mass and Inertia: Determine how much an object resists linear and angular acceleration. Matter.js automatically computes mass and moment of inertia based on shape dimensions and density.
- Velocity and Force: Motion is computed using a variation of Verlet integration. Instead of storing acceleration, the engine tracks position and velocity, applying external forces (like gravity or user input) during each frame update.
- Friction and Restitution: Restitution defines elasticity (bounciness), while static and dynamic friction parameters govern resistance when surfaces slide against each other.
Collision Detection Pipeline
Matter.js uses a two-phase collision detection pipeline to maintain high performance when handling hundreds of moving bodies:
- Broadphase: The engine first performs an inexpensive pass using Axis-Aligned Bounding Boxes (AABB). By comparing the outer boundaries of objects, it quickly discards pairs that are too far apart to touch, producing a list of potential collision pairs.
- Narrowphase: For pairs that pass the broadphase, Matter.js executes the Separating Axis Theorem (SAT). SAT tests if a line (axis) can be drawn between two convex shapes where their projections do not overlap. If no separating axis exists, a collision is confirmed, and the engine calculates the penetration depth, collision normal, and contact points.
Collision Resolution and Constraint Solving
Once contacts are determined, the engine resolves overlaps to prevent objects from clipping through one another. Matter.js applies impulse-based dynamics:
- Positional Correction: Directly separates overlapping bodies based on their relative masses to eliminate interpenetration.
- Velocity Impulses: Instantaneous changes in linear and angular velocity are calculated and applied at the contact points, accounting for conservation of momentum, surface friction, and restitution.
Matter.js also includes a constraint solver used for joints, springs, and ropes. Constraints connect two bodies (or one body to a fixed point in space) and enforce distance limits. The solver iteratively adjusts the positions and velocities of constrained bodies across multiple solver iterations per frame to achieve stability and minimize drift.
The Simulation Loop
Every tick of the simulation advances the physical world by a
discrete time step (delta). The Engine.update
cycle executes the following sequence:
- Apply global forces (e.g., gravity) and custom external forces to all bodies.
- Update spatial structures and run the broadphase collision detection.
- Execute the narrowphase collision detection via SAT to generate contact manifolds.
- Solve active constraints iteratively.
- Solve collision impulses and adjust velocities.
- Integrate velocities to update body positions and rotations.
- Clear applied forces and dispatch collision events
(
collisionStart,collisionActive,collisionEnd).