- name
- physics-matter
- description
- Use this skill when using Matter.js physics in Phaser 4. Covers rigid bodies, constraints, composite bodies, sensors, collision filtering, world configuration, and advanced physics shapes. Triggers on: Matter, matter physics, constraint, joint, rigid body, sensor.
# Matter.js Physics
> Setting up and using Matter.js physics in Phaser 4 -- full-body physics with rigid bodies, compound bodies, constraints, composites, sensors, collision filtering, pointer dragging, tilemap integration, and debug rendering.
**Key source paths:** `src/physics/matter-js/MatterPhysics.js`, `src/physics/matter-js/World.js`, `src/physics/matter-js/Factory.js`, `src/physics/matter-js/MatterSprite.js`, `src/physics/matter-js/MatterImage.js`, `src/physics/matter-js/MatterGameObject.js`, `src/physics/matter-js/PointerConstraint.js`, `src/physics/matter-js/MatterTileBody.js`, `src/physics/matter-js/components/`, `src/physics/matter-js/events/`, `src/physics/matter-js/typedefs/`
**Related skills:** ../game-setup-and-config/SKILL.md, ../sprites-and-images/SKILL.md, ../physics-arcade/SKILL.md, ../tilemaps/SKILL.md
## Quick Start
```js
class GameScene extends Phaser.Scene {
create() {
// Matter sprite (dynamic, has animation support)
this.player = this.matter.add.sprite(400, 200, 'player');
this.player.setBounce(0.5);
this.player.setFriction(0.05);
// Matter image (dynamic, no animation)
const box = this.matter.add.image(300, 100, 'crate');
// Static body from raw shape
this.matter.add.rectangle(400, 580, 800, 40, { isStatic: true });
// Enable pointer dragging on all bodies
this.matter.add.mouseSpring();
this.cursors = this.input.keyboard.createCursorKeys();
}
update() {
if (this.cursors.left.isDown) {
this.player.setVelocityX(-5);
} else if (this.cursors.right.isDown) {
this.player.setVelocityX(5);
}
if (this.cursors.up.isDown && this.player.body.velocity.y > -0.1) {
this.player.setVelocityY(-10);
}
}
}
// Enable Matter physics in game config
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
physics: {
default: 'matter',
matter: {
gravity: { y: 1 },
enableSleeping: true,
debug: true,
setBounds: true // walls around canvas edges
}
},
scene: GameScene
};
const game = new Phaser.Game(config);
```
## Core Concepts
### Scene Plugin (`this.matter`)
The `MatterPhysics` class is the scene-level plugin. Key properties:
- **`this.matter.add`** -- `Factory` for creating bodies, constraints, Game Objects (auto-added to world).
- **`this.matter.world`** -- `World` instance managing the engine, bounds, debug rendering. Extends `EventEmitter`.
- **`this.matter.body`** / **`bodies`** / **`composite`** / **`composites`** / **`constraint`** -- Direct references to Matter.js modules for low-level use.
- **`this.matter.bodyBounds`** -- Helper for aligning bodies by visual bounds.
### World (`this.matter.world`)
- **`engine`** -- The `MatterJS.Engine` instance.
- **`localWorld`** -- The `MatterJS.World` composite containing all bodies and constraints.
- **`enabled`** -- Boolean; `false` pauses simulation. **`autoUpdate`** -- `true` = engine updates each game step.
- **`walls`** -- `{ left, right, top, bottom }` boundary wall bodies (or null).
### World Config (`MatterWorldConfig`)
Passed under `physics.matter` in game or scene config:
| Property | Default | Purpose |
|---|---|---|
| `gravity` | `{ x: 0, y: 1 }` | Gravity vector. Set `false` to disable |
| `setBounds` | `false` | `true` or `{ x, y, width, height, thickness, left, right, top, bottom }` |
| `enableSleeping` | `false` | Allow bodies to sleep when at rest |
| `positionIterations` | `6` | Position solving accuracy |
| `velocityIterations` | `4` | Velocity solving accuracy |
| `constraintIterations` | `2` | Constraint stability |
| `timing.timeScale` | `1` | `0` freezes, `0.5` slow-motion |
| `autoUpdate` | `true` | Auto-step each game frame |
| `debug` | `false` | `true` or `MatterDebugConfig` object |
| `runner` | `{}` | Use `runner.fps` for fixed timestep |
### Matter Game Objects
Phaser provides two physics-aware Game Object classes and a function to add physics to any Game Object:
- **`Phaser.Physics.Matter.Sprite`** -- Extends `Sprite` with all Matter components. Created via `this.matter.add.sprite(x, y, key, frame, options)`. Supports animations.
- **`Phaser.Physics.Matter.Image`** -- Extends `Image` with all Matter components. Created via `this.matter.add.image(x, y, key, frame, options)`. No animation support, lighter weight.
- **`MatterGameObject(world, gameObject, options)`** -- Injects all Matter components into any existing Game Object. Created via `this.matter.add.gameObject(mySprite, options)`.
Both `MatterSprite` and `MatterImage` default to a rectangle body matching the texture size. Pass `options.shape` to override.
### Matter Components (Mixins)
All Matter Game Objects have these component methods mixed in:
| Component | Key Methods |
|---|---|
| **Velocity** | `setVelocity(x, y)`, `setVelocityX(x)`, `setVelocityY(y)`, `getVelocity()`, `setAngularVelocity(v)`, `getAngularVelocity()`, `setAngularSpeed(s)`, `getAngularSpeed()` |
| **Force** | `applyForce(vec2)`, `applyForceFrom(position, force)`, `thrust(speed)`, `thrustLeft(speed)`, `thrustRight(speed)`, `thrustBack(speed)` |
| **Bounce** | `setBounce(value)` -- restitution, 0 to 1 |
| **Friction** | `setFriction(value, air?, fstatic?)`, `setFrictionAir(value)`, `setFrictionStatic(value)` |
| **Mass** | `setMass(value)`, `setDensity(value)`, `centerOfMass` (getter) |
| **Gravity** | `setIgnoreGravity(bool)` |
| **Sensor** | `setSensor(bool)`, `isSensor()` |
| **Static** | `setStatic(bool)`, `isStatic()` |
| **Sleep** | `setToSleep()`, `setAwake()`, `setSleepThreshold(n)`, `setSleepEvents(start, end)` |
| **Collision** | `setCollisionCategory(cat)`, `setCollisionGroup(group)`, `setCollidesWith(cats)`, `setOnCollide(cb)`, `setOnCollideEnd(cb)`, `setOnCollideActive(cb)`, `setOnCollideWith(body, cb)` |
| **SetBody** | `setRectangle(w, h, opts)`, `setCircle(r, opts)`, `setPolygon(r, sides, opts)`, `setTrapezoid(w, h, slope, opts)`, `setBody(config, opts)`, `setExistingBody(body)` |
| **Transform** | Position sync between Matter body and Game Object |
## Common Patterns
### Setup and World Configuration
```js
// Runtime gravity and bounds
this.matter.world.setGravity(0, 2); // x, y, scale (default 0.001)
this.matter.world.disableGravity();
this.matter.world.setBounds(0, 0, 1600, 1200, 64, true, true, true, true);
this.matter.set60Hz(); // fixed timestep
this.matter.world.autoUpdate = false; // then manual: this.matter.step(16.666);
this.matter.pause(); // pause/resume
this.matter.resume();
```
### Creating Matter Sprites and Images
```js
const player = this.matter.add.sprite(200, 300, 'hero'); // default rect body matching texture
// Custom body shapes via options.shape
const ball = this.matter.add.image(400, 100, 'ball', null, { shape: { type: 'circle', radius: 24 } });
const hex = this.matter.add.sprite(300, 100, 'hex', null, { shape: { type: 'polygon', sides: 6, radius: 32 } });
const ship = this.matter.add.sprite(400, 200, 'ship', null, {
shape: { type: 'fromVerts', verts: '0 0 40 0 40 40 20 60 0 40' }
});
// PhysicsEditor shape data
const shapes = this.cache.json.get('shapes');
const enemy = this.matter.add.sprite(500, 200, 'enemy', null, { shape: shapes.enemy });
// Add Matter physics to an existing Game Object
const existingSprite = this.add.sprite(100, 100, 'box');
this.matter.add.gameObject(existingSprite, { restitution: 0.8 });
// existingSprite now has setVelocity, setBounce, etc.
```
### Body Configuration Options (`MatterBodyConfig`)
Pass as the `options` parameter to any factory method or as the options for a Matter Game Object:
- `label`, `isStatic`, `isSensor`, `angle` (radians), `timeScale`, `ignoreGravity`, `ignorePointer`
- `density` (0.001 default, auto-calculates mass), `mass`, `restitution` (bounce 0-1)
- `friction` (0-1), `frictionAir` (air resistance), `frictionStatic` (stickiness when still)
- `slop` (overlap tolerance), `chamfer` (`{ radius: 5 }` for rounded corners)
- `collisionFilter: { category: 0x0001, mask: 0xFFFFFFFF, group: 0 }`
- `onCollideCallback`, `onCollideEndCallback`, `onCollideActiveCallback`
- `shape` (for Game Objects): `{ type: 'circle', radius: 24 }` or PhysicsEditor data
### Velocity, Forces, and Thrust
```js
sprite.setVelocity(3, -5); // units per step, not pixels/sec
sprite.setVelocityX(-3);
sprite.setAngularVelocity(0.05);
const vel = sprite.getVelocity(); // { x, y }
// Forces use very small values (0.01 - 0.1)
sprite.applyForce({ x: 0.05, y: 0 });
sprite.applyForceFrom(position, { x: 0.02, y: -0.02 });
// Directional thrust relative to body angle
sprite.thrust(0.05); // forward
sprite.thrustBack(0.05); // backward
sprite.thrustLeft(0.03); // strafe left
sprite.thrustRight(0.03); // strafe right
// Batch operations via this.matter
this.matter.setVelocity(arrayOfBodies, 2, -3);
this.matter.applyForce(arrayOfBodies, { x: 0.01, y: 0 });
```
### Constraints (Joints and Springs)
```js
// constraint(bodyA, bodyB, length?, stiffness?, options?) -- aliases: joint, spring
const rigid = this.matter.add.constraint(bodyA, bodyB, 100, 1); // rigid joint
const spring = this.matter.add.constraint(bodyA, bodyB, 200, 0.02, { damping: 0.05 });
const pin = this.matter.add.constraint(bodyA, bodyB, 0, 0.9); // pin joint
// World constraint (one body pinned to world point)
this.matter.add.worldConstraint(body, 50, 0.5, { pointA: { x: 400, y: 100 } });
// Offset attachment points
this.matter.add.constraint(bodyA, bodyB, 80, 1, {
pointA: { x: 20, y: 0 }, // offset from bodyA center
pointB: { x: -20, y: 0 } // offset from bodyB center
});
this.matter.getConstraintLength(constraint); // distance between anchor points
this.matter.world.removeConstraint(constraint); // remove from world
```
### Composites (Stacks, Chains, Soft Bodies)
```js
// Stack of bodies in a grid
const stack = this.matter.add.stack(100, 100, 5, 4, 10, 10, (x, y) => {
return this.matter.bodies.rectangle(x, y, 40, 40);
});
// Image stack (grid of Matter Images)
const imageStack = this.matter.add.imageStack('crate', null, 100, 100, 5, 4, 5, 5);
// Chain bodies in a composite together
Voir sur GitHub