Matter Physics
Full rigid-body simulation for stacking, joints, compound bodies, and anything Arcade can't model.
Matter is the heavyweight physics option. It models true rigid bodies — with rotation, friction, restitution, joints, constraints, and arbitrary polygon shapes — at the cost of more CPU per body and a more complex API surface.
When to use Matter
Choose Matter the moment you need any of:
- Rotation. A tilted box that comes to rest on a slope at the correct angle.
- Stacking. A pile of boxes that settles realistically.
- Joints / constraints. Ropes, chains, hinges, springs, motorized wheels.
- Compound bodies. A vehicle with a chassis plus separate wheels.
- Polygon collision. A non-rectangular hitbox.
For everything else, prefer Arcade — it’s an order of magnitude faster.
Enabling Matter
new Phaser.Game({
physics: {
default: 'matter',
matter: {
gravity: { y: 1 }, // Matter's gravity scale, not pixels/s^2
debug: false,
enableSleeping: true, // stop integrating bodies that have settled
},
},
});
Inside a scene, this.matter is the world.
Creating bodies
// A rectangle body — easiest case.
const box = this.matter.add.image(200, 100, 'crate');
// A circle.
const ball = this.matter.add.image(300, 100, 'ball', undefined, { shape: 'circle' });
// A polygon from explicit vertices.
const tri = this.matter.add.fromVertices(400, 100, '0 0 60 0 30 50', { friction: 0.4 });
// A compound body — useful when one object needs multiple distinct hitboxes.
const ship = this.matter.add.image(500, 100, 'ship', undefined, {
shape: { type: 'fromVerts', verts: shipHullPath, flagInternal: true },
});
Common per-body properties:
box.setStatic(false);
box.setFriction(0.3, 0.001, 0.05); // surface, air, static
box.setBounce(0.4);
box.setMass(2);
box.setAngularVelocity(0.05);
Constraints and joints
// A pendulum — a static anchor with a swinging weight.
// Anchors don't need a texture; a small invisible rectangle body is enough.
const anchor = this.matter.add.rectangle(400, 50, 4, 4, { isStatic: true });
const weight = this.matter.add.image(400, 200, 'weight');
this.matter.add.constraint(anchor, weight, 150, 0.9);
// A rope of N segments.
let prev = anchor;
for (let i = 0; i < 10; i++) {
const segment = this.matter.add.image(400 + i * 10, 80, 'link');
this.matter.add.constraint(prev, segment, 12, 0.9);
prev = segment;
}
constraint(a, b, length, stiffness) — stiffness: 1 is a rigid rod, stiffness: 0.001 is a soft spring.
A live example
A small stack of boxes settling on the floor.
Performance: sleeping
Matter is much more expensive per body than Arcade. The single largest mitigation is sleeping — bodies that haven’t moved in a while are temporarily removed from the integration loop. Enable it in the config (enableSleeping: true); a settled stack costs nearly nothing until something disturbs it.
Other knobs:
positionIterationsandvelocityIterations— raise for more accurate stacks at the cost of CPU. Default 6/4 is usually fine.- Body count. Matter scales sub-linearly but not for free. A few hundred awake bodies is comfortable on desktop, ~50 on mid-range mobile.
- Don’t query the world on every frame. Use Matter’s collision events (
'collisionstart','collisionactive','collisionend') instead of scanning.
Integration with the display list
Matter game objects are normal Phaser game objects — they live in the scene’s display list, get tinted and animated like sprites, and can be parented to containers. Their position and rotation are driven by the physics body each frame; writing to .x/.y directly works but desynchronizes the body until the next physics step.
Related
- Arcade Physics — the faster, less expressive sibling.
- Game Loop — how the physics world is stepped each frame.