Claude-skill-registry dev-phaser-physics-matter
Matter.js physics: realistic bodies, constraints, and simulation
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/dev-phaser-physics-matter" ~/.claude/skills/majiayu000-claude-skill-registry-dev-phaser-physics-matter && rm -rf "$T"
manifest:
skills/data/dev-phaser-physics-matter/SKILL.mdsource content
Phaser Matter Physics
"Realistic physics simulation for puzzles and complex interactions."
Before/After: Manual Physics vs Matter.js Constraints
❌ Before: Manual Physics Simulation
// 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
// 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
// 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
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
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
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
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
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
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
// 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 — Underlying physics engine
- Phaser Matter Docs — Phaser integration