phaser-arcade-physics
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChinesePhaser 3 Arcade Physics
Phaser 3 Arcade Physics
Add movement and collision to a Phaser 3 game with the lightweight Arcade
Physics engine (AABB rectangles and circles only). Targets Phaser 3.90.
借助轻量级的Arcade Physics引擎(仅支持AABB矩形和圆形碰撞),为Phaser 3游戏添加移动和碰撞功能。本文针对Phaser 3.90版本。
When to use
使用场景
- Use for top-down or platformer movement, velocity/acceleration/gravity, bouncing, world bounds, and collision/overlap resolution between sprites, groups, and tiles.
- Use when the scene enables and code calls
physics: { default: 'arcade' },this.physics.add.*, orbody.setVelocity.this.physics.add.collider
When not to use: the config, scene structure, asset loading, or
cameras → use . Hinges, springs, complex polygons, or stacking
rigid bodies → use Matter physics (a different engine; Arcade and Matter bodies
do not interact). For engine-agnostic feel tuning see .
Gamephaser-corephysics-tuning- 适用于俯视角或平台跳跃类游戏的移动、速度/加速度/重力设置、弹跳效果、世界边界限制,以及精灵、组和瓦片之间的碰撞/重叠检测处理。
- 当场景配置中启用,且代码中调用
physics: { default: 'arcade' }、this.physics.add.*或body.setVelocity时使用。this.physics.add.collider
不适用于以下场景:游戏配置、场景结构、资源加载或相机相关操作 → 请使用。铰链、弹簧、复杂多边形或堆叠刚体 → 请使用Matter物理引擎(这是另一个不同的引擎;Arcade和Matter的物理体无法交互)。若需进行引擎无关的手感调优,请参考。
phaser-corephysics-tuningCore workflow
核心工作流程
- Enable the world. Set in the game or scene config. Turn
physics: { default: 'arcade', arcade: { gravity: {...}, debug: true } }on while building to see body outlines and velocity vectors.debug - Give a sprite a body. Create it with (dynamic) or
this.physics.add.sprite(...)(static), or attach to an existing object withthis.physics.add.staticImage(...).this.physics.add.existing(obj) - Drive it through the body, not by setting /
x. Usey,setVelocity, gravity,setAcceleration, andsetBounce. The engine integrates position from velocity each step (already frame-rate independent).setCollideWorldBounds - Resolve interactions. separates bodies;
this.physics.add.collider(a, b)detects without separating (pickups, triggers). Pass a callback to react.this.physics.add.overlap(a, b, cb) - Group many objects. Use (dynamic) or
this.physics.add.group()(platforms) so one collider call handles all members.staticGroup() - Check ground contact with /
body.onFloor()before jumping. Run withbody.blocked.downand confirm bodies, contacts, and bounds.debug: true
- 启用物理世界。在游戏或场景配置中设置。开发阶段开启
physics: { default: 'arcade', arcade: { gravity: {...}, debug: true } }模式,可查看物理体轮廓和速度向量。debug - 为精灵添加物理体。使用创建动态物理体,或使用
this.physics.add.sprite(...)创建静态物理体;也可通过this.physics.add.staticImage(...)为已有对象附加物理体。this.physics.add.existing(obj) - 通过物理体控制移动,而非直接设置/
x。使用y、setVelocity、重力、setAcceleration和setBounce。引擎会在每一步根据速度计算位置(已实现帧率无关)。setCollideWorldBounds - 处理交互。会分离发生碰撞的物理体;
this.physics.add.collider(a, b)仅检测重叠而不分离(适用于拾取物、触发器等场景)。可传入回调函数来响应交互。this.physics.add.overlap(a, b, cb) - 批量管理对象。使用(动态组)或
this.physics.add.group()(平台组),这样一次碰撞器调用即可处理组内所有成员。staticGroup() - 检测地面接触。跳跃前使用/
body.onFloor()检查是否接触地面。开启body.blocked.down模式,确认物理体、接触点和边界是否正常。debug: true
Patterns
实现模式
1. Enable Arcade Physics (game config)
1. 启用Arcade Physics(游戏配置)
js
const config = {
type: Phaser.AUTO,
width: 800, height: 600,
physics: {
default: 'arcade',
arcade: {
gravity: { x: 0, y: 600 }, // top-down? use { x: 0, y: 0 }
debug: false // true to draw bodies + velocity while building
}
},
scene: [PlayScene]
};
new Phaser.Game(config);js
const config = {
type: Phaser.AUTO,
width: 800, height: 600,
physics: {
default: 'arcade',
arcade: {
gravity: { x: 0, y: 600 }, // 俯视角游戏?请设置为{ x: 0, y: 0 }
debug: false // 开发阶段设为true可绘制物理体和速度向量
}
},
scene: [PlayScene]
};
new Phaser.Game(config);2. Top-down movement (velocity from input)
2. 俯视角移动(基于输入设置速度)
js
create() {
this.player = this.physics.add.sprite(400, 300, 'player');
this.player.setCollideWorldBounds(true);
this.cursors = this.input.keyboard.createCursorKeys();
}
update() {
const speed = 220;
const body = this.player.body;
body.setVelocity(0); // reset each frame
if (this.cursors.left.isDown) body.setVelocityX(-speed);
if (this.cursors.right.isDown) body.setVelocityX(speed);
if (this.cursors.up.isDown) body.setVelocityY(-speed);
if (this.cursors.down.isDown) body.setVelocityY(speed);
body.velocity.normalize().scale(speed); // keep diagonals same speed
}js
create() {
this.player = this.physics.add.sprite(400, 300, 'player');
this.player.setCollideWorldBounds(true);
this.cursors = this.input.keyboard.createCursorKeys();
}
update() {
const speed = 220;
const body = this.player.body;
body.setVelocity(0); // 每帧重置速度
if (this.cursors.left.isDown) body.setVelocityX(-speed);
if (this.cursors.right.isDown) body.setVelocityX(speed);
if (this.cursors.up.isDown) body.setVelocityY(-speed);
if (this.cursors.down.isDown) body.setVelocityY(speed);
body.velocity.normalize().scale(speed); // 保持斜向移动速度一致
}3. Platformer jump (gravity + ground check)
3. 平台跳跃(重力+地面检测)
js
create() {
this.player = this.physics.add.sprite(100, 450, 'player');
this.player.setCollideWorldBounds(true);
// Static platforms: one body each, never moved by collisions.
this.platforms = this.physics.add.staticGroup();
this.platforms.create(400, 568, 'ground');
this.physics.add.collider(this.player, this.platforms);
this.cursors = this.input.keyboard.createCursorKeys();
}
update() {
const onGround = this.player.body.blocked.down; // or this.player.body.onFloor()
if (this.cursors.left.isDown) this.player.setVelocityX(-160);
else if (this.cursors.right.isDown) this.player.setVelocityX(160);
else this.player.setVelocityX(0);
if (this.cursors.up.isDown && onGround) this.player.setVelocityY(-450);
}js
create() {
this.player = this.physics.add.sprite(100, 450, 'player');
this.player.setCollideWorldBounds(true);
// 静态平台:每个平台对应一个物理体,碰撞时不会被推动
this.platforms = this.physics.add.staticGroup();
this.platforms.create(400, 568, 'ground');
this.physics.add.collider(this.player, this.platforms);
this.cursors = this.input.keyboard.createCursorKeys();
}
update() {
const onGround = this.player.body.blocked.down; // 或使用this.player.body.onFloor()
if (this.cursors.left.isDown) this.player.setVelocityX(-160);
else if (this.cursors.right.isDown) this.player.setVelocityX(160);
else this.player.setVelocityX(0);
if (this.cursors.up.isDown && onGround) this.player.setVelocityY(-450);
}4. Colliders vs overlaps (separate vs detect)
4. 碰撞器与重叠检测(分离vs检测)
js
// Push apart and react: player vs enemies.
this.physics.add.collider(this.player, this.enemies, (player, enemy) => {
this.handleHit(player, enemy);
});
// Detect without pushing: collect coins. The 4th arg is an optional
// process callback returning a boolean to filter pairs before the main callback.
this.physics.add.overlap(this.player, this.coins, (player, coin) => {
coin.disableBody(true, true); // deactivate + hide
this.registry.inc('score', 10);
});js
// 分离物理体并响应:玩家vs敌人
this.physics.add.collider(this.player, this.enemies, (player, enemy) => {
this.handleHit(player, enemy);
});
// 仅检测重叠不分离:收集金币。第四个参数是可选的处理回调函数,返回布尔值用于在主回调前过滤配对
this.physics.add.overlap(this.player, this.coins, (player, coin) => {
coin.disableBody(true, true); // 禁用并隐藏金币
this.registry.inc('score', 10);
});5. A group of moving objects
5. 移动对象组
js
this.bullets = this.physics.add.group({
defaultKey: 'bullet',
maxSize: 30 // pool size; reuse instead of allocating
});
fire(x, y) {
const bullet = this.bullets.get(x, y); // reuses a dead bullet if available
if (!bullet) return;
bullet.enableBody(true, x, y, true, true);
bullet.setVelocityY(-500);
}js
this.bullets = this.physics.add.group({
defaultKey: 'bullet',
maxSize: 30 // 对象池大小;复用对象而非重新创建
});
fire(x, y) {
const bullet = this.bullets.get(x, y); // 若有闲置子弹则复用
if (!bullet) return;
bullet.enableBody(true, x, y, true, true);
bullet.setVelocityY(-500);
}Pitfalls
常见陷阱
- Sprite ignores physics → it was added with instead of
this.add.sprite(orthis.physics.add.sprite), so it has no body.this.physics.add.existing(obj) - Setting directly fights the engine → move dynamic bodies with
sprite.x/setVelocity. Direct position writes can tunnel through colliders.setAcceleration - Diagonal movement is faster → independent X and Y velocities add up; normalise the velocity vector and rescale to the intended speed.
- Platforms get pushed by the player → use a , or set
staticGroupon a dynamic platform.body.setImmovable(true) - is always false → the body needs something to collide with; add the
onFloor()against the ground/platforms before checking, and ensure gravity is on.collider - Moved a static body but collisions are stale → static bodies don't auto-sync;
call (or
body.updateFromGameObject()on the game object).refreshBody() - Collider added every frame → register /
collideronce inoverlap, not increate.update
- 精灵无视物理规则 → 你使用了而非
this.add.sprite(或this.physics.add.sprite),因此精灵没有物理体。this.physics.add.existing(obj) - 直接设置会与引擎冲突 → 使用
sprite.x/setVelocity控制动态物理体移动。直接修改位置可能导致穿透碰撞体。setAcceleration - 斜向移动速度更快 → 独立设置X和Y速度会导致速度叠加;需归一化速度向量并重新缩放至预期速度。
- 平台被玩家推动 → 使用,或为动态平台设置
staticGroup。body.setImmovable(true) - 始终返回false → 物理体需要有可碰撞的对象;在检测前添加与地面/平台的碰撞器,并确保已启用重力。
onFloor() - 移动静态物理体后碰撞状态未更新 → 静态物理体不会自动同步;调用(或在游戏对象上调用
body.updateFromGameObject())。refreshBody() - 每帧都添加碰撞器 → 在中注册一次
create/collider,不要在overlap中重复注册。update
References
参考资料
- For body anatomy and tuning (drag, bounce, max velocity, custom /
setSize/setCirclehitboxes, collision categories/masks, andsetOffsetevents), readworldbounds.references/bodies-and-collision.md
- 关于物理体结构和调优(阻力、弹跳、最大速度、自定义/
setSize/setCircle碰撞盒、碰撞分类/掩码、setOffset事件),请阅读worldbounds。references/bodies-and-collision.md
Related skills
相关技能
- — game config, scenes, loader, cameras (the prerequisite setup).
phaser-core - — engine-agnostic feel (fixed timestep, tunneling, jitter).
physics-tuning - /
platformer— genres that compose this skill.tower-defense - — laying out tile/platform geometry these bodies collide with.
level-design
- — 游戏配置、场景、资源加载器、相机(必备基础设置)。
phaser-core - — 引擎无关的手感调优(固定时间步长、穿透问题、抖动)。
physics-tuning - /
platformer— 需结合此技能的游戏类型。tower-defense - — 物理体碰撞的瓦片/平台布局设计。
level-design