Phaser 4 Matter.js 物理系统实战指南:刚体、约束、复合体、传感器与碰撞过滤完整解析
【免费下载链接】phaserPhaser is a fun, free and fast 2D game framework for making HTML5 games for desktop and mobile web browsers, supporting Canvas and WebGL rendering.项目地址: https://gitcode.com/gh_mirrors/ph/phaser
本文基于 Phaser 仓库中的官方技能文档(skills/physics-matter/SKILL.md)展开,系统讲解如何在 Phaser 4 场景中启用与使用 Matter.js 全刚体物理引擎。你将掌握刚体与复合体创建、约束(关节/弹簧)、传感器、碰撞过滤、指针拖拽、Tilemap 集成以及调试渲染的完整配置与调用方式,并能在实际项目中直接套用文中全部示例代码。
Matter.js 是 Phaser 内置的全刚体(full-body)物理引擎。与 Arcade Physics 的简化 AABB 碰撞不同,它支持刚性体、复合体、复合结构体、凸/凹多边形碰撞体、质量与密度、恢复系数(restitution)、稳定堆叠、动量守恒、约束、重力、休眠(sleeping)与静态体、圆角(chamfering)、碰撞查询(raycast、区域检测)以及时间缩放(慢动作/加速)等能力。下文将以场景插件this.matter为入口,从启用配置到高级玩法逐层展开。
快速开始:一个可运行的 Matter 场景
启用 Matter 物理只需要两步:在游戏配置中声明default: 'matter',并在场景中通过this.matter.add工厂创建物理对象。
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);注意update中的跳跃判断:this.player.body.velocity.y > -0.1用于近似判断玩家是否“已落地”(Matter 中速度单位为“每步的单位数”而非像素/秒),避免空中无限连跳。
核心概念:场景插件、世界与配置
场景插件this.matter(MatterPhysics)
MatterPhysics是场景级插件,负责 Phaser Scene 与单个 Matter Engine 实例之间的桥接(见 MatterPhysics.js 类注释)。它的关键属性:
this.matter.add—Factory实例,用于创建刚体、约束和物理 Game Object,并自动加入世界。在 boot 方法 中实例化。this.matter.world—World实例,管理引擎、边界、调试渲染,继承自EventEmitter(见 World.js)。this.matter.body/bodies/composite/composites/constraint— 对 Matter.js 底层模块的直接引用(分别指向Matter.Body、Matter.Bodies、Matter.Composite、Matter.Composites、Matter.Constraint),用于脱离 Phaser 封装的低层操作。this.matter.bodyBounds—BodyBounds辅助类,用于按视觉边界对齐刚体(见 BodyBounds.js)。
世界this.matter.world
World在构造时即调用Engine.create(config)创建 Matter 引擎,并持有localWorld(包含所有刚体与约束的 World 复合体)。常用属性:
engine—MatterJS.Engine实例。localWorld—MatterJS.World复合体,包含所有刚体与约束。enabled— 布尔值,false时暂停模拟;autoUpdate为true时每个游戏帧自动执行引擎步进。walls—{ left, right, top, bottom }边界墙刚体(未启用时为null)。
世界配置(MatterWorldConfig)
配置通过游戏配置或场景配置的physics.matter传入,其字段定义见 MatterWorldConfig.js:
| 属性 | 默认值 | 作用 |
|---|---|---|
gravity | { x: 0, y: 1 } | 重力向量;设为false可禁用 |
setBounds | false | true或{ x, y, width, height, thickness, left, right, top, bottom };其中thickness默认 64,四个方向墙体默认均创建 |
enableSleeping | false | 允许刚体静止时休眠,可提升稳定性与性能 |
positionIterations | 6 | 位置求解精度,越大模拟质量越高但性能越低 |
velocityIterations | 4 | 速度求解精度 |
constraintIterations | 2 | 约束稳定性 |
timing.timeScale | 1 | 0冻结模拟,0.1慢动作,1.2加速 |
enabled | true | 世界是否启用 |
correction | 1 | 应用于更新的时间校正因子 |
autoUpdate | true | 每个游戏帧自动调用Engine.update |
restingThresh | 4 | Resolver 静止阈值 |
restingThreshTangent | 6 | Resolver 静止切向阈值 |
positionDampen | 0.9 | Resolver 位置阻尼 |
positionWarming | 0.8 | Resolver 位置预热 |
frictionNormalMultiplier | 5 | Resolver 摩擦法向乘数 |
debug | false | true或MatterDebugConfig对象 |
runner | {} | Matter Runner 选项,runner.fps用于固定时间步长 |
从源码 MatterPhysics.js 可以看到,restingThresh、positionDampen等求解器参数在插件构造时通过GetValue(this.config, ...)读取并写入Resolver模块。配置合并逻辑位于 getConfig 方法:场景配置优先于游戏配置(sceneConfig的matter覆盖gameConfig的matter)。
setBounds与迭代次数等物理参数在 World.js 的setBounds(第 796 行)、引擎创建逻辑中生效。
Matter Game Object:三种接入方式
Phaser 提供两个内置物理 Game Object 类,以及一个可给任意 Game Object 注入物理能力的函数:
Phaser.Physics.Matter.Sprite— 继承Sprite并混入全部 Matter 组件,通过this.matter.add.sprite(x, y, key, frame, options)创建,支持动画。实现见 MatterSprite.js。Phaser.Physics.Matter.Image— 继承Image并混入全部 Matter 组件,通过this.matter.add.image(x, y, key, frame, options)创建,无动画支持、更轻量。实现见 MatterImage.js。MatterGameObject(world, gameObject, options)— 把全部 Matter 组件注入任意已有 Game Object,通过this.matter.add.gameObject(mySprite, options)创建。实现见 MatterGameObject.js。
MatterSprite与MatterImage默认按纹理尺寸生成矩形刚体,可通过options.shape覆盖默认形状。对应工厂方法位于 Factory.js:image(820 行)、tileBody(849 行)、sprite(876 行)、gameObject(904 行)。
Matter 组件(Mixin)速查
所有 Matter Game Object 都会混入以下组件方法,组件源码位于 components/ 目录(对应 12 个 mixin 文件:Bounce、Collision、Force、Friction、Gravity、Mass、Sensor、SetBody、Sleep、Static、Transform、Velocity):
| 组件 | 关键方法 |
|---|---|
| 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)— 恢复系数,范围 0~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 | 同步 Matter 刚体与 Game Object 之间的位置 |
常见模式详解
世界配置与运行时调整
// 运行时调整重力与边界 this.matter.world.setGravity(0, 2); // 参数:x, y, scale(默认 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();set60Hz()/set30Hz()的实现是把world.getDelta指向update60Hz/update30Hz并强制autoUpdate = true(见 MatterPhysics.js),World中对应的步进函数见 World.js 第 1307、1320 行。step(delta)则会绕过enabled/autoUpdate检查直接推进一帧模拟。
创建 Sprite / Image 与自定义形状
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 导出的形状 JSON const shapes = this.cache.json.get('shapes'); const enemy = this.matter.add.sprite(500, 200, 'enemy', null, { shape: shapes.enemy }); // 给已有 Game Object 注入物理能力 const existingSprite = this.add.sprite(100, 100, 'box'); this.matter.add.gameObject(existingSprite, { restitution: 0.8 }); // existingSprite 现在拥有了 setVelocity、setBounce 等方法PhysicsEditor JSON 的解析由 PhysicsEditorParser.js 完成;工厂侧fromPhysicsEditor与其对应,另支持fromSVG(把 SVG 路径转为顶点)与fromJSON。
刚体配置选项(MatterBodyConfig)
作为任意工厂方法的options参数传入:
label、isStatic、isSensor、angle(弧度)、timeScale、ignoreGravity、ignorePointerdensity(默认 0.001,根据密度自动计算质量)、mass、restitution(弹性/反弹 0~1)friction(0~1)、frictionAir(空气阻力)、frictionStatic(静止时的黏滞)slop(重叠容差)、chamfer({ radius: 5 }圆角)collisionFilter: { category: 0x0001, mask: 0xFFFFFFFF, group: 0 }onCollideCallback、onCollideEndCallback、onCollideActiveCallbackshape(仅 Game Object 使用):{ type: 'circle', radius: 24 }或 PhysicsEditor 数据
完整字段定义见 MatterBodyConfig.js 与 MatterCollisionFilter.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 });约束(关节与弹簧)
constraint(bodyA, bodyB, length?, stiffness?, options?)同时提供joint、spring两个别名(见 Factory.js 第 612、644、674 行的joint、spring、constraint):
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); // 从世界移除复合体(堆叠、链条、软体)
// 网格状堆叠 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 }); // 软体(参数顺序:x, y, cols, rows, colGap, rowGap, 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);上述方法的工厂签名均可在 Factory.js 中确认:imageStack(394 行)、stack(437 行)、pyramid(463 行)、chain(487 行)、mesh(506 行)、newtonsCradle(525 行)、car(548 行)、softBody(576 行)。
复合刚体(Compound Bodies)
把多个形状合并为单个刚体,第一个部件作为父体:
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] }); // 挂到 Game Object 上 const player = this.matter.add.sprite(400, 200, 'hero'); player.setExistingBody(compoundBody);所有部件共享位置、角度与速度。约束必须作用于父体,不能直接作用在子部件(parts)上。
休眠系统(Sleep)
静止的刚体可以休眠以跳过模拟,需要先在配置中开启enableSleeping: true:
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)
传感器检测碰撞但不产生物理反应,适合触发区域、拾取物、探测区:
const trigger = this.matter.add.rectangle(400, 300, 100, 100, { isSensor: true, isStatic: true }); sprite.setSensor(true); // 在 Game Object 上切换 sprite.isSensor(); // 查询状态 // 传感器同样触发普通碰撞事件——用 collisionstart/end 判断进出碰撞分类与过滤
Matter 使用位掩码:category(该刚体属于哪一组,须为 2 的幂)、mask(该刚体与哪些类别碰撞)以及group(快捷方式:相同正数 = 总是碰撞,相同负数 = 永不碰撞,0 = 使用 category/mask):
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);nextCategory()与nextGroup(isNonColliding)的实现位于 World.js 第 1095、1109 行。
碰撞回调
// 按刚体设置回调(Matter Game Object 上) player.setOnCollide((pair) => { /* pair.bodyA, pair.bodyB */ }); player.setOnCollideEnd((pair) => { /* 碰撞结束 */ }); player.setOnCollideActive((pair) => { /* 仍在碰撞中 */ }); player.setOnCollideWith(enemy, (body, pair) => { /* 命中特定刚体 */ }); // Game Object 级别事件(在 Game Object 本身上触发) player.on('collide', (bodyA, bodyB, pair) => {}); player.on('collideEnd', (bodyA, bodyB, pair) => {});Tilemap 集成
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]);底层实现由 MatterTileBody.js 包装瓦片与 Matter 刚体,convertTilemapLayer/convertTiles见 World.js 第 1045、1069 行。
三类摩擦
Matter.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); // 一次设置全部三项:动摩擦、空气、静摩擦由顶点构造复杂形状
// 从顶点字符串创建刚体(凹形会自动分解为凸形) 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);凹形的凸分解依赖poly-decomp库,其在 MatterPhysics.js 通过Common.setDecomp(require('./poly-decomp'))注入(模块位于 poly-decomp/)。
指针约束(鼠标/触屏拖拽)
// 启用对所有 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) => {});实现位于 PointerConstraint.js,工厂入口mouseSpring/ 别名pointerConstraint见 Factory.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('Overlapping', bodyA, bodyB); });调试渲染
// 在 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);debug支持布尔值或完整的MatterDebugConfig对象(如showBody、showStaticBody、showBroadphase、showSleeping、staticBodySleepOpacity等),全部字段与默认值见 MatterDebugConfig.js,渲染样式设置见 World.js 第 387、474 行的setBodyRenderStyle/setConstraintRenderStyle。
事件系统
所有事件都通过this.matter.world触发(World继承自EventEmitter,见 World.js),并代理全部 Matter.js 底层事件。事件常量定义于 events/ 目录:
| 事件 | 回调签名 | 触发时机 |
|---|---|---|
'collisionstart' | (event, bodyA, bodyB) | 两个刚体首次开始碰撞 |
'collisionactive' | (event, bodyA, bodyB) | 两个刚体仍在碰撞中 |
'collisionend' | (event, bodyA, bodyB) | 两个刚体停止碰撞 |
'beforeupdate' | (event) | 引擎步进更新前 |
'afterupdate' | (event) | 引擎步进更新后 |
'beforeadd' | (event) | 刚体/约束被添加前 |
'afteradd' | (event) | 刚体/约束被添加后 |
'beforeremove' | (event) | 刚体/约束被移除前 |
'afterremove' | (event) | 刚体/约束被移除后 |
'dragstart' | (body, part, constraint) | 指针开始拖拽刚体 |
'drag' | (body, constraint) | 指针正在拖拽刚体 |
'dragend' | (body, constraint) | 指针停止拖拽刚体 |
'sleepstart' | (event, body) | 刚体入睡(需启用setSleepEvents) |
'sleepend' | (event, body) | 刚体唤醒(需启用setSleepEvents) |
'pause' | 无 | 世界暂停 |
'resume' | 无 | 世界恢复 |
碰撞事件包含event.pairs—— 碰撞对数组,每个元素含bodyA、bodyB、碰撞深度与法线。世界暂停/恢复的实现见 World.js 第 1125、1143 行的pause/resume。
API 快速参考
this.matter.add(Factory)
- Game Objects:
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?)(别名joint、spring)、worldConstraint(body, len?, stiff?, opts?)、mouseSpring(opts?)(别名pointerConstraint) - 复合体:
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)批量与工具方法
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()
this.matter上的 Matter.js 底层模块引用
body(Matter.Body)、bodies(Matter.Bodies)、composite(Matter.Composite)、composites(Matter.Composites)、constraint(Matter.Constraint)、collision(Matter.Collision)、detector、query、pair、pairs、resolver、axes、bounds、svg、vector、vertices(别名verts)。这些模块的完整清单与用途注释见 MatterPhysics.js,对应底层库文件位于 lib/(含 Body、Composite、World、Detector、Engine、Bodies、Composites、Vertices、Constraint 等完整 Matter.js 模块)。
易踩的坑(Gotchas)
- 力的数值极小。力用
0.01~0.1,速度用1~15。两者都不是像素单位。 setBody/setRectangle等会重置所有属性—— 质量、摩擦、碰撞过滤、回调都会被清空,更换形状后需要重新设置。- 约束必须指向父体,不能指向复合刚体的
parts子部件。 - 碰撞类别最多 32 个。每次
nextCategory()占用一个 bit。 collisionFilter.group优先于 category/mask。相同正数 = 总是碰撞;相同负数 = 永不碰撞;0 或不同 = 回退到 category/mask。- 传感器仍需匹配的碰撞过滤条件才会触发事件。
- Matter 位置是质心,不是左上角(与 Arcade Physics 不同)。
- 休眠事件需要显式开启:
sprite.setSleepEvents(true, true)。 - Tilemap 转换前必须先设置碰撞(如
setCollisionByProperty)。 - 恢复系数取
Math.max(bodyA.restitution, bodyB.restitution)—— 弹力更大的一方决定结果。 body.ignorePointer = true可阻止指针约束拖拽该刚体。
源码文件地图
| 路径 | 职责 |
|---|---|
| src/physics/matter-js/MatterPhysics.js | 场景插件(this.matter),暴露全部 Matter 模块 |
| src/physics/matter-js/World.js | 世界管理、引擎、边界、调试、事件代理 |
| src/physics/matter-js/Factory.js | this.matter.add—— 全部创建方法 |
| src/physics/matter-js/MatterSprite.js | 物理精灵(Sprite + Matter 组件) |
| src/physics/matter-js/MatterImage.js | 物理图像(Image + Matter 组件) |
| src/physics/matter-js/MatterGameObject.js | 向任意 Game Object 注入 Matter 组件 |
| src/physics/matter-js/MatterTileBody.js | 用 Matter 刚体包装单个瓦片 |
| src/physics/matter-js/PointerConstraint.js | 点击拖拽刚体约束 |
| src/physics/matter-js/BodyBounds.js | 按视觉边界对齐刚体 |
| src/physics/matter-js/PhysicsEditorParser.js | 解析 PhysicsEditor JSON 为刚体 |
| src/physics/matter-js/components/ | Mixin:Velocity、Force、Collision、SetBody、Sensor、Bounce、Friction、Mass、Gravity、Static、Sleep、Transform |
| src/physics/matter-js/events/ | 事件常量(COLLISION_START、DRAG_START、SLEEP_START 等) |
| src/physics/matter-js/typedefs/ | TypeDefs:MatterWorldConfig、MatterBodyConfig、MatterCollisionFilter、MatterConstraintConfig、MatterDebugConfig 等 |
| src/physics/matter-js/lib/ | 打包进 Phaser 的 Matter.js 库模块 |
关联技能与进一步阅读
Matter 物理通常与以下主题配合使用:游戏初始化与配置(skills/game-setup-and-config/SKILL.md)、精灵与图像创建(skills/sprites-and-images/SKILL.md)、轻量级物理替代方案 Arcade Physics(skills/physics-arcade/SKILL.md)以及瓦片地图关卡搭建(skills/tilemaps/SKILL.md)。若需从 Phaser 3 迁移到 Phaser 4,可参考 skills/v3-to-v4-migration/SKILL.md。
【免费下载链接】phaserPhaser is a fun, free and fast 2D game framework for making HTML5 games for desktop and mobile web browsers, supporting Canvas and WebGL rendering.项目地址: https://gitcode.com/gh_mirrors/ph/phaser
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考