---
name: dev-phaser-physics-matter
description: Matter.js physics: realistic bodies, constraints, and simulation
---

# Phaser Matter Physics

> "Realistic physics simulation for puzzles and complex interactions."

## Before/After: Manual Physics vs Matter.js Constraints

### ❌ Before: Manual Physics Simulation

```typescript
// Manual physics without proper engine
interface Body {
  x: number; y: number;
  vx: number; vy: number;
  mass: number;
  angle: number;
  angularVelocity: number;
}

const bodies: Body[] = [];

function updatePhysics(dt: number) {
  // Apply gravity
  for (const body of bodies) {
    body.vy += 9.8 * dt;
  }

  // Check collisions (O(n²) complexity)
  for (let i = 0; i < bodies.length; i++) {
    for (let j = i + 1; j < bodies.length; j++) {
      if (checkCollision(bodies[i], bodies[j])) {
        resolveCollision(bodies[i], bodies[j]);
      }
    }
  }

  // Update positions
  for (const body of bodies) {
    body.x += body.vx * dt;
    body.y += body.vy * dt;
    body.angle += body.angularVelocity * dt;
  }
}

// Problems:
// - O(n²) collision detection
// - No realistic stacking
// - No constraints/joints
// - Manual collision resolution
// - No rotational physics
```

### ✅ After: Phaser Matter Physics

```typescript
// Matter.js handles complex physics
export class GameScene extends Phaser.Scene {
  create() {
    // Enable Matter physics
    this.physics.world.setBounds(0, 0, 800, 600);

    // Create connected bodies with constraint
    const box1 = this.matter.add.image(300, 200, 'box');
    box1.setRectangle(40, 40);
    box1.setStatic(true);

    const box2 = this.matter.add.image(300, 300, 'box');
    box2.setRectangle(40, 40);

    // Create chain constraint (rope-like) - ONE line!
    this.matter.add.constraint(box1, box2, 100, 0.9, {
      render: { visible: true }
    });

    // Add spring constraint
    const springBox = this.matter.add.image(500, 200, 'box');
    this.matter.add.spring(
      { x: 500, y: 100 },
      springBox,
      100,
      0.001,
      { damping: 0.05 }
    );
  }
}

// Benefits:
// - Efficient SAT collision detection
// - Realistic stacking behavior
// - Built-in constraints (chains, springs, hinges)
// - Rotational physics included
// - Sleep optimization for performance
```

## When to Use This Skill

Use when:

- Building physics puzzle games
- Need realistic collision and physics
- Working with complex body shapes
- Using constraints and joints
- Simulating realistic object interactions

## Quick Start

```typescript
// Enable Matter physics in game config
physics: {
  default: 'matter',
  matter: {
    gravity: { y: 1 },
    debug: false
  }
}

// Create Matter sprite
const box = this.matter.add.image(400, 300, 'box');
box.setRectangle();
```

## Decision Framework

| Need               | Use                  |
| ------------------ | -------------------- |
| Physics puzzles    | Matter physics       |
| Realistic stacking | Matter with friction |
| Ropes/chains       | Constraints          |
| Complex shapes     | Custom body vertices |
| Simple platformer  | Arcade instead       |

## Progressive Guide

### Level 1: Basic Matter Bodies

```typescript
export class GameScene extends Phaser.Scene {
  create() {
    // Create image as Matter body
    const box = this.matter.add.image(400, 100, "box");
    box.setRectangle(); // Default: use texture size
    box.setBounce(0.5);
    box.setFriction(0.1);

    // Circle body
    const ball = this.matter.add.image(400, 200, "ball");
    ball.setCircle();
    ball.setBounce(0.8);

    // Static ground
    const ground = this.matter.add.image(400, 550, "ground");
    ground.setStatic(true);
    ground.setRectangle(800, 50);
  }
}
```

### Level 2: Custom Body Shapes

```typescript
create() {
  // Triangle body
  const triangle = this.matter.add.image(400, 100, 'triangle');
  triangle.setPolygon(0, 0, [
    { x: 0, y: -30 },
    { x: 30, y: 30 },
    { x: -30, y: 30 }
  ]);

  // Custom shape from vertices
  const rock = this.matter.add.image(400, 200, 'rock');
  rock.setPolygon(0, 0, [
    { x: -25, y: -20 },
    { x: 20, y: -25 },
    { x: 30, y: 10 },
    { x: 10, y: 30 },
    { x: -20, y: 25 }
  ]);

  // Compound body (multiple shapes)
  const compound = this.matter.add.image(400, 300, 'crate');
  compound.setRectangle(40, 40);
  compound.setBounce(0.2);
  compound.setFriction(0.5);
}
```

### Level 3: Constraints and Joints

```typescript
create() {
  const box1 = this.matter.add.image(300, 200, 'box');
  box1.setRectangle(40, 40);
  box1.setStatic(true);

  const box2 = this.matter.add.image(300, 300, 'box');
  box2.setRectangle(40, 40);

  // Create chain constraint (rope-like)
  this.matter.add.constraint(box1, box2, 100, 0.9, {
    render: { visible: true }
  });

  // Create hinge constraint
  const door = this.matter.add.image(400, 300, 'door');
  door.setRectangle(10, 100);
  this.matter.add.constraint(door, { x: 400, y: 250 }, 50, 1, {
    pointA: { x: 0, y: -50 },
    pointB: { x: 0, y: 0 }
  });

  // Spring constraint
  const springBox = this.matter.add.image(500, 200, 'box');
  springBox.setRectangle(40, 40);

  this.matter.add.spring(
    { x: 500, y: 100 },
    springBox,
    100,
    0.001,
    { damping: 0.05 }
  );
}
```

### Level 4: Physics Events and Collision

```typescript
create() {
  // Collision event
  this.matter.world.on('collisionstart', (event: any) => {
    event.pairs.forEach((pair: any) => {
      const bodyA = pair.bodyA;
      const bodyB = pair.bodyB;

      if (bodyA.label === 'player' && bodyB.label === 'coin') {
        this.collectCoin(bodyB.gameObject);
      }
    });
  });

  // Create labeled bodies
  const player = this.matter.add.image(400, 300, 'player');
  player.setRectangle();
  (player.body as MatterJS.Body).label = 'player';

  const coin = this.matter.add.image(400, 400, 'coin');
  coin.setCircle();
  (coin.body as MatterJS.Body).label = 'coin';
}
```

### Level 5: Advanced Matter Physics

```typescript
export class PhysicsScene extends Phaser.Scene {
  private bridgeParts: Phaser.Physics.Matter.Image[] = [];

  create() {
    this.createBridge();
    this.createRope();
    this.createPhysicsStack();
  }

  createBridge() {
    const startX = 200;
    const startY = 200;
    const plankCount = 8;
    const plankWidth = 60;
    const gap = 5;

    let previousPlank: Phaser.Physics.Matter.Image | null = null;

    for (let i = 0; i < plankCount; i++) {
      const x = startX + i * (plankWidth + gap);
      const y = startY;

      const plank = this.matter.add.image(x, y, "plank");
      plank.setRectangle(plankWidth, 20);
      plank.setBounce(0);
      plank.setFriction(0.8);

      this.bridgeParts.push(plank);

      if (i === 0 || i === plankCount - 1) {
        plank.setStatic(true);
      }

      if (previousPlank) {
        this.matter.add.constraint(
          previousPlank,
          plank,
          plankWidth + gap,
          0.9,
          {
            pointA: { x: plankWidth / 2, y: 0 },
            pointB: { x: -plankWidth / 2, y: 0 },
          },
        );
      }

      previousPlank = plank;
    }
  }

  createRope() {
    const links = 10;
    const linkLength = 20;
    const startX = 600;
    const startY = 100;

    let prevLink: Phaser.Physics.Matter.Image | null = null;

    for (let i = 0; i < links; i++) {
      const link = this.matter.add.circle(startX, startY + i * linkLength, 5);
      link.setBounce(0);
      link.setFriction(0.5);

      if (i === 0) {
        link.setStatic(true);
      }

      if (prevLink) {
        this.matter.add.constraint(prevLink, link, linkLength, 0.9);
      }

      prevLink = link;
    }
  }

  createPhysicsStack() {
    const stackSize = 5;
    const boxSize = 40;
    const startX = 500;
    const startY = 500;

    for (let row = 0; row < stackSize; row++) {
      for (let col = 0; col < stackSize - row; col++) {
        const x = startX + col * boxSize + row * (boxSize / 2);
        const y = startY - row * boxSize;

        const box = this.matter.add.image(x, y, "box");
        box.setRectangle(boxSize, boxSize);
        box.setBounce(0.1);
        box.setFriction(0.5);
        box.setDensity(0.001);
      }
    }
  }
}
```

## Anti-Patterns

❌ **DON'T:**

- Use Matter for simple platformers - Arcade is better
- Set high density on all objects - causes instability
- Ignore sleep settings - kills performance
- Create complex constraints without tuning
- Mix body coordinates systems arbitrarily
- Forget to set static on anchored objects

✅ **DO:**

- Use Matter for puzzles, stacking, complex interactions
- Adjust density based on object type
- Enable sleep for inactive bodies
- Test constraint values iteratively
- Keep coordinates consistent
- Set static bodies for anchors/ground

## Code Patterns

### Body Configuration

```typescript
const box = this.matter.add.image(400, 300, "box");

// Shape
box.setRectangle(width, height);
box.setCircle(radius);
box.setPolygon(x, y, vertices);
box.setTrapezoid(width, height, slope);

// Physics properties
box.setBounce(0.5); // Restitution
box.setFriction(0.1); // Surface friction
box.setFrictionStatic(0.5); // Static friction
box.setDensity(0.001); // Mass = density * area
box.setAngle(Math.PI / 4); // Rotation in radians

// State
box.setStatic(true); // Immovable
box.setSensor(true); // Detect but don't collide
```

### Constraint Types

```typescript
// Chain constraint (rigid-ish connection)
this.matter.add.constraint(bodyA, bodyB, length, stiffness);

// Spring constraint
this.matter.add.spring(bodyA, bodyB, length, stiffness, config);

// World constraint (anchor to point)
this.matter.add.constraint(body, { x, y }, length, stiffness);

// Hinge (rotational joint)
this.matter.add.constraint(bodyA, bodyB, length, stiffness, {
  pointA: { x: offsetX, y: offsetY },
  pointB: { x: offsetX, y: offsetY },
});
```

## Matter vs Arcade Comparison

| Feature     | Arcade                | Matter                     |
| ----------- | --------------------- | -------------------------- |
| Performance | Faster                | Slower                     |
| Complexity  | Simple                | Complex                    |
| Collision   | AABB/OBB              | SAT/Polygon                |
| Constraints | Basic                 | Advanced                   |
| Best For    | Platformers, top-down | Puzzles, realistic physics |
| Body Types  | Dynamic/Static        | Dynamic/Static/Sensor      |

## Checklist

- [ ] Matter physics enabled in config
- [ ] Bodies properly shaped
- [ ] Static bodies marked as static
- [ ] Constraints tuned properly
- [ ] Collision labels set for events
- [ ] Density/bounce/friction configured
- [ ] Sleep enabled for performance

## Reference

- [Matter.js Docs](https://brm.io/matter-js-docs/) — Underlying physics engine
- [Phaser Matter Docs](https://photonstorm.github.io/phaser3-docs/Phaser.Physics.Matter.MatterPhysics.html) — Phaser integration


---
Source attribution: feliperyba
Original project: https://github.com/feliperyba/ralph-orchestra/blob/7a74951367fe9bec093753f6eaa4d0eeda9428e5/.claude/skills/dev-phaser-physics-matter/SKILL.md
License: MIT
License information: https://opensource.org/license/mit
Original upstream instructions; downloaded from Dave AI.

## Upstream license notice

MIT License

Copyright (c) 2026 feliperyba

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.



# Dave AI resource metadata

Creator / publisher: feliperyba
Original project: https://github.com/feliperyba/ralph-orchestra/blob/7a74951367fe9bec093753f6eaa4d0eeda9428e5/.claude/skills/dev-phaser-physics-matter/SKILL.md
Attribution basis: Recovered original package and original project license at a pinned revision

Fields of work: Development & Engineering
Roles: Frontend Developer, Game Developer
Specialties: Backend, Mobile
Tools: Phaser
Country applicability: Country not specified
Classification basis: Source catalog labels
Instruction SHA-256: 21df2488c6e1fa63a75cfd42279b3604527f54de4ca39a00d362d3cbbc7bac43
Metadata reviewed: 2026-10-27
This metadata supersedes earlier Dave AI catalog attribution. Original instruction and supporting files are preserved.
