physics-matter
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseMatter.js Physics
Matter.js 物理引擎
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: , , , , , , , , , ,
Related skills: ../game-setup-and-config/SKILL.md, ../sprites-and-images/SKILL.md, ../physics-arcade/SKILL.md, ../tilemaps/SKILL.md
src/physics/matter-js/MatterPhysics.jssrc/physics/matter-js/World.jssrc/physics/matter-js/Factory.jssrc/physics/matter-js/MatterSprite.jssrc/physics/matter-js/MatterImage.jssrc/physics/matter-js/MatterGameObject.jssrc/physics/matter-js/PointerConstraint.jssrc/physics/matter-js/MatterTileBody.jssrc/physics/matter-js/components/src/physics/matter-js/events/src/physics/matter-js/typedefs/在Phaser 4中设置和使用Matter.js物理引擎——包含刚体、复合物体、约束、组合体、传感器、碰撞过滤、指针拖拽、瓦片地图集成以及调试渲染的全功能物理系统。
核心源码路径: , , , , , , , , , ,
相关技能: ../game-setup-and-config/SKILL.md, ../sprites-and-images/SKILL.md, ../physics-arcade/SKILL.md, ../tilemaps/SKILL.md
src/physics/matter-js/MatterPhysics.jssrc/physics/matter-js/World.jssrc/physics/matter-js/Factory.jssrc/physics/matter-js/MatterSprite.jssrc/physics/matter-js/MatterImage.jssrc/physics/matter-js/MatterGameObject.jssrc/physics/matter-js/PointerConstraint.jssrc/physics/matter-js/MatterTileBody.jssrc/physics/matter-js/components/src/physics/matter-js/events/src/physics/matter-js/typedefs/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);js
class GameScene extends Phaser.Scene {
create() {
// Matter sprite(动态,支持动画)
this.player = this.matter.add.sprite(400, 200, 'player');
this.player.setBounce(0.5);
this.player.setFriction(0.05);
// Matter image(动态,无动画)
const box = this.matter.add.image(300, 100, 'crate');
// 基于原始形状创建静态物体
this.matter.add.rectangle(400, 580, 800, 40, { isStatic: true });
// 启用所有物体的指针拖拽功能
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);
}
}
}
// 在游戏配置中启用Matter物理引擎
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
physics: {
default: 'matter',
matter: {
gravity: { y: 1 },
enableSleeping: true,
debug: true,
setBounds: true // 画布边缘创建墙体
}
},
scene: GameScene
};
const game = new Phaser.Game(config);Core Concepts
核心概念
Scene Plugin (this.matter
)
this.matter场景插件(this.matter
)
this.matterThe class is the scene-level plugin. Key properties:
MatterPhysics- --
this.matter.addfor creating bodies, constraints, Game Objects (auto-added to world).Factory - --
this.matter.worldinstance managing the engine, bounds, debug rendering. ExtendsWorld.EventEmitter - /
this.matter.body/bodies/composite/composites-- Direct references to Matter.js modules for low-level use.constraint - -- Helper for aligning bodies by visual bounds.
this.matter.bodyBounds
MatterPhysics- -- 用于创建物体、约束、游戏对象(自动添加到物理世界)的工厂类。
this.matter.add - -- 管理物理引擎、边界、调试渲染的
this.matter.world实例,继承自World。EventEmitter - /
this.matter.body/bodies/composite/composites-- 直接引用Matter.js模块,用于底层操作。constraint - -- 辅助工具,用于按视觉边界对齐物理物体。
this.matter.bodyBounds
World (this.matter.world
)
this.matter.world物理世界(this.matter.world
)
this.matter.world- -- The
engineinstance.MatterJS.Engine - -- The
localWorldcomposite containing all bodies and constraints.MatterJS.World - -- Boolean;
enabledpauses simulation.false--autoUpdate= engine updates each game step.true - --
wallsboundary wall bodies (or null).{ left, right, top, bottom }
- --
engine实例。MatterJS.Engine - -- 包含所有物体和约束的
localWorld组合体。MatterJS.World - -- 布尔值;设为
enabled时暂停物理模拟。false-- 设为autoUpdate时,引擎会在每帧游戏步骤中更新。true - -- 边界墙体物体(结构为
walls,无边界时为null)。{ left, right, top, bottom }
World Config (MatterWorldConfig
)
MatterWorldConfig物理世界配置(MatterWorldConfig
)
MatterWorldConfigPassed under in game or scene config:
physics.matter| Property | Default | Purpose |
|---|---|---|
| | Gravity vector. Set |
| | |
| | Allow bodies to sleep when at rest |
| | Position solving accuracy |
| | Velocity solving accuracy |
| | Constraint stability |
| | |
| | Auto-step each game frame |
| | |
| | Use |
在游戏或场景配置的字段中传入:
physics.matter| 属性 | 默认值 | 用途 |
|---|---|---|
| | 重力向量,设为 |
| | 设为 |
| | 允许静止物体进入休眠状态,减少性能消耗 |
| | 位置求解精度 |
| | 速度求解精度 |
| | 约束稳定性 |
| | 时间缩放, |
| | 每帧自动执行物理引擎更新步骤 |
| | 设为 |
| | 使用 |
Matter Game Objects
Matter游戏对象
Phaser provides two physics-aware Game Object classes and a function to add physics to any Game Object:
- -- Extends
Phaser.Physics.Matter.Spritewith all Matter components. Created viaSprite. Supports animations.this.matter.add.sprite(x, y, key, frame, options) - -- Extends
Phaser.Physics.Matter.Imagewith all Matter components. Created viaImage. No animation support, lighter weight.this.matter.add.image(x, y, key, frame, options) - -- Injects all Matter components into any existing Game Object. Created via
MatterGameObject(world, gameObject, options).this.matter.add.gameObject(mySprite, options)
Both and default to a rectangle body matching the texture size. Pass to override.
MatterSpriteMatterImageoptions.shapePhaser提供了两个支持物理的游戏对象类,以及一个为任意游戏对象添加物理属性的方法:
- -- 继承自
Phaser.Physics.Matter.Sprite,集成所有Matter组件。通过Sprite创建,支持动画。this.matter.add.sprite(x, y, key, frame, options) - -- 继承自
Phaser.Physics.Matter.Image,集成所有Matter组件。通过Image创建,不支持动画,更轻量化。this.matter.add.image(x, y, key, frame, options) - -- 为任意现有游戏对象注入Matter组件。通过
MatterGameObject(world, gameObject, options)创建。this.matter.add.gameObject(mySprite, options)
MatterSpriteMatterImageoptions.shapeMatter Components (Mixins)
Matter组件(混合类)
All Matter Game Objects have these component methods mixed in:
| Component | Key Methods |
|---|---|
| Velocity | |
| Force | |
| Bounce | |
| Friction | |
| Mass | |
| Gravity | |
| Sensor | |
| Static | |
| Sleep | |
| Collision | |
| SetBody | |
| Transform | Position sync between Matter body and Game Object |
所有Matter游戏对象都集成了以下组件方法:
| 组件 | 核心方法 |
|---|---|
| Velocity(速度) | |
| Force(力) | |
| Bounce(弹性) | |
| Friction(摩擦力) | |
| Mass(质量) | |
| Gravity(重力) | |
| Sensor(传感器) | |
| Static(静态) | |
| Sleep(休眠) | |
| Collision(碰撞) | |
| SetBody(设置物体形状) | |
| Transform(变换) | 同步Matter物理体与游戏对象的位置 |
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();js
// 运行时修改重力和边界
this.matter.world.setGravity(0, 2); // x, y, 缩放比例(默认0.001)
this.matter.world.disableGravity();
this.matter.world.setBounds(0, 0, 1600, 1200, 64, true, true, true, true);
this.matter.set60Hz(); // 设置固定时间步长为60Hz
this.matter.world.autoUpdate = false; // 关闭自动更新,手动调用:this.matter.step(16.666);
this.matter.pause(); // 暂停物理模拟
this.matter.resume(); // 恢复物理模拟Creating Matter Sprites and Images
创建Matter精灵与图片
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.js
const player = this.matter.add.sprite(200, 300, 'hero'); // 默认使用与纹理匹配的矩形物理体
// 通过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导出的形状数据
const shapes = this.cache.json.get('shapes');
const enemy = this.matter.add.sprite(500, 200, 'enemy', null, { shape: shapes.enemy });
// 为现有游戏对象添加Matter物理属性
const existingSprite = this.add.sprite(100, 100, 'box');
this.matter.add.gameObject(existingSprite, { restitution: 0.8 });
// existingSprite现在拥有setVelocity、setBounce等方法Body Configuration Options (MatterBodyConfig
)
MatterBodyConfig物理体配置选项(MatterBodyConfig
)
MatterBodyConfigPass as the parameter to any factory method or as the options for a Matter Game Object:
options- ,
label,isStatic,isSensor(radians),angle,timeScale,ignoreGravityignorePointer - (0.001 default, auto-calculates mass),
density,mass(bounce 0-1)restitution - (0-1),
friction(air resistance),frictionAir(stickiness when still)frictionStatic - (overlap tolerance),
slop(chamferfor rounded corners){ radius: 5 } collisionFilter: { category: 0x0001, mask: 0xFFFFFFFF, group: 0 }- ,
onCollideCallback,onCollideEndCallbackonCollideActiveCallback - (for Game Objects):
shapeor PhysicsEditor data{ type: 'circle', radius: 24 }
可作为工厂方法的参数传入,或作为Matter游戏对象的配置选项:
options- ,
label,isStatic,isSensor(弧度),angle,timeScale,ignoreGravityignorePointer - (默认0.001,自动计算质量),
density,mass(弹性,0-1)restitution - (0-1),
friction(空气阻力),frictionAir(静止时的粘性)frictionStatic - (重叠容差),
slop(chamfer设置圆角){ radius: 5 } collisionFilter: { category: 0x0001, mask: 0xFFFFFFFF, group: 0 }- ,
onCollideCallback,onCollideEndCallbackonCollideActiveCallback - (游戏对象专用):
shape或PhysicsEditor数据{ type: 'circle', radius: 24 }
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 });js
sprite.setVelocity(3, -5); // 单位为每步数值,非像素/秒
sprite.setVelocityX(-3);
sprite.setAngularVelocity(0.05);
const vel = sprite.getVelocity(); // 返回{ x, y }
// 力的取值非常小(建议0.01 - 0.1)
sprite.applyForce({ x: 0.05, y: 0 });
sprite.applyForceFrom(position, { x: 0.02, y: -0.02 });
// 相对于物体角度的定向推力
sprite.thrust(0.05); // 向前
sprite.thrustBack(0.05); // 向后
sprite.thrustLeft(0.03); // 向左平移
sprite.thrustRight(0.03); // 向右平移
// 通过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 worldjs
// constraint(bodyA, bodyB, length?, stiffness?, options?) -- 别名:joint、spring
const rigid = this.matter.add.constraint(bodyA, bodyB, 100, 1); // 刚性关节
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); // 销钉关节
// 世界约束(将单个物体固定到世界坐标点)
this.matter.add.worldConstraint(body, 50, 0.5, { pointA: { x: 400, y: 100 } });
// 设置偏移附着点
this.matter.add.constraint(bodyA, bodyB, 80, 1, {
pointA: { x: 20, y: 0 }, // 相对于bodyA中心的偏移
pointB: { x: -20, y: 0 } // 相对于bodyB中心的偏移
});
this.matter.getConstraintLength(constraint); // 获取锚点间距离
this.matter.world.removeConstraint(constraint); // 从物理世界中移除约束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);js
// 网格状堆叠物体
const stack = this.matter.add.stack(100, 100, 5, 4, 10, 10, (x, y) => {
return this.matter.bodies.rectangle(x, y, 40, 40);
});
// 图片堆叠(网格状Matter Image)
const imageStack = this.matter.add.imageStack('crate', null, 100, 100, 5, 4, 5, 5);
// 将组合体中的物体链接成链条
this.matter.add.chain(stack, 0.5, 0, -0.5, 0, { stiffness: 0.7 });
// 网格(带约束的网格,可选交叉支撑)
this.matter.add.mesh(stack, 5, 4, true, { stiffness: 0.5 });
// 软体(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 });
// 预定义组合体:牛顿摆、汽车、金字塔
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.
将多个形状组合成单个物理体,第一个部分作为父物体。
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] });
// 将复合物体附加到游戏对象
const player = this.matter.add.sprite(400, 200, 'hero');
player.setExistingBody(compoundBody);所有部分共享位置、角度和速度。约束必须指向父物体,而非复合物体的子部分。
Sleep System
休眠系统
Bodies at rest can sleep to skip simulation. Requires in config.
enableSleeping: truejs
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 */ });静止物体可进入休眠状态以跳过模拟计算,需在配置中设置。
enableSleeping: truejs
if (body.isSleeping) { /* 物体处于静止休眠状态 */ }
sprite.setSleepThreshold(30); // 值越小,物体越快进入休眠(默认60)
sprite.setToSleep(); // 强制物体进入休眠
sprite.setAwake(); // 强制物体唤醒
sprite.setSleepEvents(true, true); // 启用sleepstart/sleepend事件
this.matter.world.on('sleepstart', (event, body) => { /* 物体进入休眠 */ });
this.matter.world.on('sleepend', (event, body) => { /* 物体唤醒 */ });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传感器可检测碰撞但不会产生物理交互,适用于触发区域、拾取物、检测范围等场景。
js
const trigger = this.matter.add.rectangle(400, 300, 100, 100, { isSensor: true, isStatic: true });
sprite.setSensor(true); // 在游戏对象上切换传感器状态
sprite.isSensor(); // 检查传感器状态
// 传感器会触发常规碰撞事件——使用collisionstart/end检测进入/离开Collision Categories and Filtering
碰撞分类与过滤
Matter uses bitmasks: (which group this body belongs to, power of 2), (which categories it collides with), and (shortcut: same positive = always collide, same negative = never collide, 0 = use category/mask).
categorymaskgroupjs
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);Matter使用位掩码:(物体所属组,必须是2的幂)、(物体可碰撞的组)、(快捷方式:相同正数=始终碰撞,相同负数=永不碰撞,0=使用category/mask规则)。
categorymaskgroupjs
const PLAYER = this.matter.world.nextCategory(); // 0x0002(最多支持32个分类)
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]); // 子弹不与玩家碰撞
// 碰撞组:相同负数=组内物体永不碰撞
const noCollide = this.matter.world.nextGroup(true);
spriteA.setCollisionGroup(noCollide);
spriteB.setCollisionGroup(noCollide);
// 通过物体配置设置:collisionFilter: { category, mask, group }
// 批量设置: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) => {});js
// 单个物体的回调(Matter游戏对象专属)
player.setOnCollide((pair) => { /* pair.bodyA, pair.bodyB */ });
player.setOnCollideEnd((pair) => { /* 碰撞结束 */ });
player.setOnCollideActive((pair) => { /* 持续碰撞中 */ });
player.setOnCollideWith(enemy, (body, pair) => { /* 碰撞指定物体 */ });
// 游戏对象级事件(由游戏对象自身触发)
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]);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 }); // 必须先设置碰撞属性
this.matter.world.convertTilemapLayer(layer); // 为每个可碰撞瓦片创建MatterTileBody
// 优先使用Tiled中定义的碰撞形状(矩形、圆形、多边形),否则使用瓦片边界。
// 访问方式:tile.physics.matterBody
// 单个瓦片:this.matter.add.tileBody(tile, { isStatic: true, friction: 0.5 });
// 地图修改后: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, staticMatter.js包含三种独立的摩擦力参数:
js
sprite.setFriction(0.1); // 动摩擦:运动时的阻力(0-1)
sprite.setFrictionStatic(0.5); // 静摩擦:开始运动前的阻力
sprite.setFrictionAir(0.05); // 空气摩擦:环境阻力(默认0.01)
sprite.setFriction(0.1, 0.02, 0.3); // 同时设置三个参数:动摩擦、空气摩擦、静摩擦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);js
// 通过顶点字符串创建物体(凹形会自动分解)
const body = this.matter.add.fromVertices(400, 300, '0 0 40 0 40 40 20 60 0 40');
// 多组顶点创建复杂形状
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) => {});js
// 启用所有Matter物体的点击拖拽功能
const pc = this.matter.add.mouseSpring({ stiffness: 0.2, damping: 0.1 });
pc.active = false; // 临时禁用拖拽
body.ignorePointer = true; // 禁止特定物体被拖拽
pc.stopDrag(); // 程序化释放当前拖拽
pc.destroy(); // 完全移除指针约束
// 物理世界的拖拽事件
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);
});js
const hits = this.matter.intersectPoint(pointer.x, pointer.y); // 获取指定点的所有物体
const contains = this.matter.containsPoint(body, x, y); // 测试点是否在物体内部
const inRegion = this.matter.intersectRect(100, 100, 200, 200); // 获取指定矩形区域内的物体
const rayHits = this.matter.intersectRay(0, 300, 800, 300, 1); // 射线检测
const colliding = this.matter.intersectBody(playerBody); // 获取与指定物体重叠的物体
// 带回调的重叠检测
this.matter.overlap(playerBody, enemyBodies, (bodyA, bodyB, info) => {
console.log('重叠物体', 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);js
// 在matter配置中传入debug属性启用调试,支持自定义选项
// 布尔选项:showBody, showStaticBody, showVelocity, showCollisions, showSensors,
// showJoint, showPositions, showBounds, showAxes, showAngleIndicator, showSleeping,
// showConvexHulls, showInternalEdges, renderFill, renderLine
// 颜色/样式选项:lineColor, lineThickness, fillColor, staticLineColor, staticFillColor,
// sensorLineColor, jointColor, pinColor, springColor, anchorColor, positionColor
// 运行时切换调试状态
this.matter.world.drawDebug = false;
this.matter.world.debugGraphic.visible = false;
// 设置单个物体或约束的渲染样式
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 (which extends ):
this.matter.worldEventEmitter| Event | Callback Signature | When |
|---|---|---|
| | Two bodies first start colliding |
| | Two bodies are still colliding |
| | Two bodies stop colliding |
| | Before engine update step |
| | After engine update step |
| | Before a body/constraint is added |
| | After a body/constraint is added |
| | Before a body/constraint is removed |
| | After a body/constraint is removed |
| | Pointer starts dragging body |
| | Pointer is dragging body |
| | Pointer stops dragging body |
| | Body goes to sleep (requires |
| | Body wakes up (requires |
| none | World paused |
| none | World resumed |
Collision events include -- an array of collision pair objects with , , collision depth, and normal.
event.pairsbodyAbodyB所有事件都在(继承自)上触发:
this.matter.worldEventEmitter| 事件 | 回调签名 | 触发时机 |
|---|---|---|
| | 两个物体首次开始碰撞时 |
| | 两个物体持续碰撞中 |
| | 两个物体停止碰撞时 |
| | 物理引擎更新步骤开始前 |
| | 物理引擎更新步骤完成后 |
| | 物体/约束被添加到物理世界前 |
| | 物体/约束被添加到物理世界后 |
| | 物体/约束被从物理世界移除前 |
| | 物体/约束被从物理世界移除后 |
| | 指针开始拖拽物体时 |
| | 指针正在拖拽物体时 |
| | 指针停止拖拽物体时 |
| | 物体进入休眠时(需先调用 |
| | 物体唤醒时(需先调用 |
| 无参数 | 物理世界暂停时 |
| 无参数 | 物理世界恢复时 |
碰撞事件包含——碰撞对数组,每个元素包含、、碰撞深度和法向量。
event.pairsbodyAbodyBAPI Quick Reference
API速查
this.matter.add
(Factory)
this.matter.addthis.matter.add
(工厂类)
this.matter.addGame Objects: , , ,
Body shapes: , , , , , , ,
Constraints: (aliases: , ), , (alias: )
Composites: , , , , , , ,
sprite(x, y, key, frame?, opts?)image(x, y, key, frame?, opts?)gameObject(go, opts?)tileBody(tile, opts?)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?)constraint(a, b, len?, stiff?, opts?)jointspringworldConstraint(body, len?, stiff?, opts?)mouseSpring(opts?)pointerConstraintstack(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)游戏对象: , , ,
物体形状: , , , , , , ,
约束: (别名:, ), , (别名:)
组合体: , , , , , , ,
sprite(x, y, key, frame?, opts?)image(x, y, key, frame?, opts?)gameObject(go, opts?)tileBody(tile, opts?)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?)constraint(a, b, len?, stiff?, opts?)jointspringworldConstraint(body, len?, stiff?, opts?)mouseSpring(opts?)pointerConstraintstack(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
this.matterthis.matter
(MatterPhysics)——批量操作与工具方法
this.matterpause()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)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)
this.matter.worldthis.matter.world
(World)
this.matter.worldsetBounds(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()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
this.matterthis.matter
上的Matter.js模块直接引用
this.matterbodybodiescompositecompositesconstraintdetectorquerypairpairsresolveraxesboundssvgvectorverticesbodybodiescompositecompositesconstraintdetectorquerypairpairsresolveraxesboundssvgvectorverticesGotchas
注意事项
- Force values are tiny. Use -
0.01for forces,0.1-1for velocity. Not pixel-based.15 - /
setBody/etc. resets all properties -- mass, friction, collision filters, callbacks are wiped. Re-apply after changing shape.setRectangle - Constraints must target parent body, not compound body .
parts - 32 collision categories max. Each uses one bit.
nextCategory() - overrides category/mask. Same positive = always collide; same negative = never collide; zero/different = use category/mask.
collisionFilter.group - 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 etc.
setCollisionByProperty - Restitution uses -- the bouncier value wins.
Math.max(bodyA.restitution, bodyB.restitution) - prevents pointer constraint from dragging that body.
body.ignorePointer = true
- 力的取值非常小:力建议使用-
0.01,速度建议使用0.1-1,单位非像素。15 - /
setBody等方法会重置所有属性——质量、摩擦力、碰撞过滤、回调都会被清除,修改形状后需重新设置。setRectangle - 约束必须指向父物体,而非复合物体的子部分。
- 最多支持32个碰撞分类:每个占用一个比特位。
nextCategory() - 会覆盖category/mask规则:相同正数=始终碰撞;相同负数=永不碰撞;0/不同值=使用category/mask规则。
collisionFilter.group - 传感器仍需匹配碰撞过滤规则才能触发事件。
- Matter物体的位置是质心,而非左上角(与Arcade Physics不同)。
- 休眠事件需要手动启用:调用。
sprite.setSleepEvents(true, true) - 瓦片地图转换必须先设置碰撞属性,比如通过等方法。
setCollisionByProperty - 恢复系数取两个物体中的较大值——。
Math.max(bodyA.restitution, bodyB.restitution) - ****会阻止指针约束拖拽该物体。
body.ignorePointer = true
Source File Map
源码文件映射
| Path | Purpose |
|---|---|
| Scene plugin ( |
| World management, engine, bounds, debug, events proxy |
| |
| Physics sprite (Sprite + Matter components) |
| Physics image (Image + Matter components) |
| Injects Matter components into any Game Object |
| Wraps a Tile with a Matter body |
| Click-and-drag body constraint |
| Body alignment by visual bounds |
| Parses PhysicsEditor JSON into bodies |
| Mixins: Velocity, Force, Collision, SetBody, Sensor, Bounce, Friction, Mass, Gravity, Static, Sleep, Transform |
| Event constants (COLLISION_START, DRAG_START, SLEEP_START, etc.) |
| TypeDefs: MatterWorldConfig, MatterBodyConfig, MatterCollisionFilter, MatterConstraintConfig, etc. |
| Bundled Matter.js library modules |
| 路径 | 用途 |
|---|---|
| 场景插件( |
| 物理世界管理、引擎、边界、调试、事件代理 |
| |
| 物理精灵(Sprite + Matter组件) |
| 物理图片(Image + Matter组件) |
| 为任意游戏对象注入Matter组件 |
| 为瓦片包装Matter物理体 |
| 点击拖拽物体的约束 |
| 通过视觉边界对齐物体的工具 |
| 将PhysicsEditor JSON解析为物理体 |
| 混合类:Velocity、Force、Collision、SetBody、Sensor、Bounce、Friction、Mass、Gravity、Static、Sleep、Transform |
| 事件常量(COLLISION_START、DRAG_START、SLEEP_START等) |
| 类型定义:MatterWorldConfig、MatterBodyConfig、MatterCollisionFilter、MatterConstraintConfig等 |
| 打包的Matter.js库模块 |