UNPKG

phaser

Version:

A fast, free and fun HTML5 Game Framework for Desktop and Mobile web browsers from the team at Phaser Studio Inc.

500 lines (382 loc) 23.8 kB
--- 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 this.matter.add.chain(stack, 0.5, 0, -0.5, 0, { stiffness: 0.7 }); // Mesh (grid with constraints, optional cross braces) this.matter.add.mesh(stack, 5, 4, true, { stiffness: 0.5 }); // Soft body (cols, rows, gaps, crossBrace, particleRadius, bodyOpts, constraintOpts) this.matter.add.softBody(200, 100, 5, 5, 0, 0, true, 10, { friction: 0.1 }, { stiffness: 0.5 }); // Pre-built composites: newtonsCradle, car, pyramid this.matter.add.newtonsCradle(300, 50, 5, 20, 200); this.matter.add.car(400, 300, 120, 30, 25); ``` ### Compound Bodies Combine multiple shapes into a single body. The first part is the parent. ```js const partA = this.matter.bodies.rectangle(0, 0, 60, 20); const partB = this.matter.bodies.circle(0, -30, 15); const compoundBody = this.matter.body.create({ parts: [partA, partB] }); // Attach to a Game Object const player = this.matter.add.sprite(400, 200, 'hero'); player.setExistingBody(compoundBody); ``` Parts share position, angle, and velocity. Constraints must target the parent body, not parts. ### Sleep System Bodies at rest can sleep to skip simulation. Requires `enableSleeping: true` in config. ```js if (body.isSleeping) { /* body is at rest */ } sprite.setSleepThreshold(30); // lower = falls asleep faster (default 60) sprite.setToSleep(); // force sleep sprite.setAwake(); // force wake sprite.setSleepEvents(true, true); // enable sleepstart/sleepend events this.matter.world.on('sleepstart', (event, body) => { /* body slept */ }); this.matter.world.on('sleepend', (event, body) => { /* body woke */ }); ``` ### Sensors Sensors detect collisions but do not physically react. Useful for trigger zones, pickups, detection areas. ```js const trigger = this.matter.add.rectangle(400, 300, 100, 100, { isSensor: true, isStatic: true }); sprite.setSensor(true); // toggle on Game Object sprite.isSensor(); // check state // Sensors fire normal collision events -- use collisionstart/end to detect entry/exit ``` ### Collision Categories and Filtering Matter uses bitmasks: `category` (which group this body belongs to, power of 2), `mask` (which categories it collides with), and `group` (shortcut: same positive = always collide, same negative = never collide, 0 = use category/mask). ```js const PLAYER = this.matter.world.nextCategory(); // 0x0002 (32 max) const ENEMY = this.matter.world.nextCategory(); // 0x0004 const GROUND = this.matter.world.nextCategory(); // 0x0008 player.setCollisionCategory(PLAYER); player.setCollidesWith([ENEMY, GROUND]); bullet.setCollisionCategory(0x0010); bullet.setCollidesWith([ENEMY, GROUND]); // bullets skip player // Collision groups: same negative = never collide with each other const noCollide = this.matter.world.nextGroup(true); spriteA.setCollisionGroup(noCollide); spriteB.setCollisionGroup(noCollide); // Via body config: collisionFilter: { category, mask, group } // Batch: this.matter.setCollisionCategory([bodyA, bodyB], ENEMY); ``` ### Collision Callbacks ```js // Per-body callbacks (on Matter Game Objects) player.setOnCollide((pair) => { /* pair.bodyA, pair.bodyB */ }); player.setOnCollideEnd((pair) => { /* collision ended */ }); player.setOnCollideActive((pair) => { /* still colliding */ }); player.setOnCollideWith(enemy, (body, pair) => { /* hit specific body */ }); // Game Object-level events (emitted on the Game Object itself) player.on('collide', (bodyA, bodyB, pair) => {}); player.on('collideEnd', (bodyA, bodyB, pair) => {}); ``` ### Tilemap Integration ```js const map = this.make.tilemap({ key: 'level' }); const tileset = map.addTilesetImage('tiles', 'tiles-img'); const layer = map.createLayer('Ground', tileset, 0, 0); layer.setCollisionByProperty({ collides: true }); // MUST set collision first this.matter.world.convertTilemapLayer(layer); // creates MatterTileBody per colliding tile // Uses Tiled collision shapes (rect, circle, polygon) if defined, otherwise tile bounds. // Access: tile.physics.matterBody // Individual tile: this.matter.add.tileBody(tile, { isStatic: true, friction: 0.5 }); // After map changes: this.matter.world.convertTiles([tile1, tile2]); ``` ### Friction Types Matter.js has three independent friction values: ```js sprite.setFriction(0.1); // dynamic: resistance during motion (0-1) sprite.setFrictionStatic(0.5); // static: resistance before motion starts sprite.setFrictionAir(0.05); // air: environmental drag (default 0.01) sprite.setFriction(0.1, 0.02, 0.3); // set all three: dynamic, air, static ``` ### Complex Shapes from Vertices ```js // Create body from vertex string (concave shapes auto-decomposed) const body = this.matter.add.fromVertices(400, 300, '0 0 40 0 40 40 20 60 0 40'); // Multiple vertex sets for complex shapes const vertexSets = [ [{ x: 0, y: 0 }, { x: 40, y: 0 }, { x: 40, y: 40 }], [{ x: 40, y: 40 }, { x: 20, y: 60 }, { x: 0, y: 40 }] ]; this.matter.add.fromVertices(300, 200, vertexSets); ``` ### Pointer Constraint (Mouse/Touch Dragging) ```js // Enable click-and-drag on all Matter bodies const pc = this.matter.add.mouseSpring({ stiffness: 0.2, damping: 0.1 }); pc.active = false; // disable temporarily body.ignorePointer = true; // prevent specific body from being dragged pc.stopDrag(); // release current drag programmatically pc.destroy(); // remove entirely // Drag events on the world this.matter.world.on('dragstart', (body, part, constraint) => {}); this.matter.world.on('drag', (body, constraint) => {}); this.matter.world.on('dragend', (body, constraint) => {}); ``` ### Queries (Raycasting and Hit Testing) ```js const hits = this.matter.intersectPoint(pointer.x, pointer.y); // bodies at point const contains = this.matter.containsPoint(body, x, y); // point-in-body test const inRegion = this.matter.intersectRect(100, 100, 200, 200); // bodies in rect const rayHits = this.matter.intersectRay(0, 300, 800, 300, 1); // raycast const colliding = this.matter.intersectBody(playerBody); // body overlap // Overlap with callbacks this.matter.overlap(playerBody, enemyBodies, (bodyA, bodyB, info) => { console.log('Overlapping', bodyA, bodyB); }); ``` ### Debug Rendering ```js // Enable debug with specific options (pass as debug property in matter config) // Boolean flags: showBody, showStaticBody, showVelocity, showCollisions, showSensors, // showJoint, showPositions, showBounds, showAxes, showAngleIndicator, showSleeping, // showConvexHulls, showInternalEdges, renderFill, renderLine // Color/style: lineColor, lineThickness, fillColor, staticLineColor, staticFillColor, // sensorLineColor, jointColor, pinColor, springColor, anchorColor, positionColor // Toggle debug at runtime this.matter.world.drawDebug = false; this.matter.world.debugGraphic.visible = false; // Set render style on individual body or constraint this.matter.world.setBodyRenderStyle(body, 0xff0000, 1, 2, 0x00ff00, 0.5); this.matter.world.setConstraintRenderStyle(constraint, 0xffff00, 1, 2); ``` ## Events All events are emitted on `this.matter.world` (which extends `EventEmitter`): | Event | Callback Signature | When | |---|---|---| | `'collisionstart'` | `(event, bodyA, bodyB)` | Two bodies first start colliding | | `'collisionactive'` | `(event, bodyA, bodyB)` | Two bodies are still colliding | | `'collisionend'` | `(event, bodyA, bodyB)` | Two bodies stop colliding | | `'beforeupdate'` | `(event)` | Before engine update step | | `'afterupdate'` | `(event)` | After engine update step | | `'beforeadd'` | `(event)` | Before a body/constraint is added | | `'afteradd'` | `(event)` | After a body/constraint is added | | `'beforeremove'` | `(event)` | Before a body/constraint is removed | | `'afterremove'` | `(event)` | After a body/constraint is removed | | `'dragstart'` | `(body, part, constraint)` | Pointer starts dragging body | | `'drag'` | `(body, constraint)` | Pointer is dragging body | | `'dragend'` | `(body, constraint)` | Pointer stops dragging body | | `'sleepstart'` | `(event, body)` | Body goes to sleep (requires `setSleepEvents`) | | `'sleepend'` | `(event, body)` | Body wakes up (requires `setSleepEvents`) | | `'pause'` | none | World paused | | `'resume'` | none | World resumed | Collision events include `event.pairs` -- an array of collision pair objects with `bodyA`, `bodyB`, collision depth, and normal. ## API Quick Reference ### `this.matter.add` (Factory) **Game Objects:** `sprite(x, y, key, frame?, opts?)`, `image(x, y, key, frame?, opts?)`, `gameObject(go, opts?)`, `tileBody(tile, opts?)` **Body shapes:** `rectangle(x, y, w, h, opts?)`, `circle(x, y, r, opts?)`, `polygon(x, y, sides, r, opts?)`, `trapezoid(x, y, w, h, slope, opts?)`, `fromVertices(x, y, verts, opts?)`, `fromPhysicsEditor(x, y, config, opts?)`, `fromSVG(x, y, xml, scale?, opts?)`, `fromJSON(x, y, config, opts?)` **Constraints:** `constraint(a, b, len?, stiff?, opts?)` (aliases: `joint`, `spring`), `worldConstraint(body, len?, stiff?, opts?)`, `mouseSpring(opts?)` (alias: `pointerConstraint`) **Composites:** `stack(x, y, cols, rows, colGap, rowGap, cb)`, `imageStack(key, frame, x, y, cols, rows)`, `pyramid(...)`, `chain(composite, xA, yA, xB, yB, opts?)`, `mesh(composite, cols, rows, cross, opts?)`, `softBody(...)`, `car(x, y, w, h, wheelSize)`, `newtonsCradle(x, y, num, size, len)` ### `this.matter` (MatterPhysics) -- batch and utility `pause()`, `resume()`, `set60Hz()`, `set30Hz()`, `step(delta?)`, `setVelocity(bodies, x, y)`, `setAngularVelocity(bodies, v)`, `applyForce(bodies, force)`, `applyForceFromAngle(bodies, speed, angle?)`, `containsPoint(body, x, y)`, `intersectPoint(x, y)`, `intersectRect(x, y, w, h, outside?)`, `intersectRay(x1, y1, x2, y2, width?)`, `intersectBody(body)`, `overlap(target, bodies?, cb?)`, `setCollisionCategory(bodies, value)`, `setCollisionGroup(bodies, value)`, `setCollidesWith(bodies, cats)`, `alignBody(body, x, y, align)` ### `this.matter.world` (World) `setBounds(x?, y?, w?, h?, thickness?, l?, r?, t?, b?)`, `setGravity(x?, y?, scale?)`, `disableGravity()`, `add(object)`, `remove(object, deep?)`, `removeConstraint(constraint)`, `convertTilemapLayer(layer, opts?)`, `convertTiles(tiles, opts?)`, `nextCategory()`, `nextGroup(isNonColliding?)`, `getAllBodies()`, `has(body)`, `pause()`, `resume()` ### Direct Matter.js module references on `this.matter` `body` (Matter.Body), `bodies` (Matter.Bodies), `composite` (Matter.Composite), `composites` (Matter.Composites), `constraint` (Matter.Constraint), `detector`, `query`, `pair`, `pairs`, `resolver`, `axes`, `bounds`, `svg`, `vector`, `vertices` ## Gotchas - **Force values are tiny.** Use `0.01`-`0.1` for forces, `1`-`15` for velocity. Not pixel-based. - **`setBody`/`setRectangle`/etc. resets all properties** -- mass, friction, collision filters, callbacks are wiped. Re-apply after changing shape. - **Constraints must target parent body**, not compound body `parts`. - **32 collision categories max.** Each `nextCategory()` uses one bit. - **`collisionFilter.group` overrides category/mask.** Same positive = always collide; same negative = never collide; zero/different = use category/mask. - **Sensors still need matching collision filters** to fire events. - **Matter position is center of mass**, not top-left (unlike Arcade Physics). - **Sleep events require opt-in:** `sprite.setSleepEvents(true, true)`. - **Tilemap conversion requires collision set first** via `setCollisionByProperty` etc. - **Restitution uses `Math.max(bodyA.restitution, bodyB.restitution)`** -- the bouncier value wins. - **`body.ignorePointer = true`** prevents pointer constraint from dragging that body. ## Source File Map | Path | Purpose | |---|---| | `src/physics/matter-js/MatterPhysics.js` | Scene plugin (`this.matter`), exposes all Matter modules | | `src/physics/matter-js/World.js` | World management, engine, bounds, debug, events proxy | | `src/physics/matter-js/Factory.js` | `this.matter.add` -- all creation methods | | `src/physics/matter-js/MatterSprite.js` | Physics sprite (Sprite + Matter components) | | `src/physics/matter-js/MatterImage.js` | Physics image (Image + Matter components) | | `src/physics/matter-js/MatterGameObject.js` | Injects Matter components into any Game Object | | `src/physics/matter-js/MatterTileBody.js` | Wraps a Tile with a Matter body | | `src/physics/matter-js/PointerConstraint.js` | Click-and-drag body constraint | | `src/physics/matter-js/BodyBounds.js` | Body alignment by visual bounds | | `src/physics/matter-js/PhysicsEditorParser.js` | Parses PhysicsEditor JSON into bodies | | `src/physics/matter-js/components/` | Mixins: Velocity, Force, Collision, SetBody, Sensor, Bounce, Friction, Mass, Gravity, Static, Sleep, Transform | | `src/physics/matter-js/events/` | Event constants (COLLISION_START, DRAG_START, SLEEP_START, etc.) | | `src/physics/matter-js/typedefs/` | TypeDefs: MatterWorldConfig, MatterBodyConfig, MatterCollisionFilter, MatterConstraintConfig, etc. | | `src/physics/matter-js/lib/` | Bundled Matter.js library modules |