Phaser 3足球游戏玩家与球体碰撞异常问题求助
解决Phaser 3足球游戏中玩家与球体仅上下碰撞的问题
问题原因
- 碰撞器重复创建:你在
update函数里每帧都调用this.physics.add.collider,会不断生成新的碰撞器,导致物理引擎冲突,碰撞检测逻辑异常。 - 直接修改坐标绕开物理系统:用
this.player.x += 2.5这种方式移动玩家,完全绕过了Phaser的物理引擎,引擎无法同步玩家位置与碰撞体状态,自然碰撞检测只在局部区域生效。 - 碰撞体与缩放图片不匹配:图片通过
setScale缩放后,默认的物理碰撞体还是原始图片尺寸,没有同步缩放,导致碰撞区域和视觉上的玩家/球体大小不对应。
修复方法
1. 把碰撞器创建移到create函数
碰撞器只需要初始化一次,放在create中即可,删除update里的碰撞器创建代码:
function create() { // ... 其他初始化代码 this.physics.add.collider(this.ball, this.player); // 移至此处 }
2. 用物理引擎方法控制玩家移动
替换直接修改坐标的方式,使用setVelocity让物理引擎管理移动,确保碰撞检测正常工作:
function update() { let speed = 200; // 可根据需求调整速度 this.player.setVelocity(0); // 先重置速度 if (this.D.isDown) { this.player.setVelocityX(speed); } else if (this.A.isDown) { this.player.setVelocityX(-speed); } if (this.W.isDown) { this.player.setVelocityY(-speed); } }
3. 同步碰撞体与缩放后的图片尺寸
创建玩家和球体后,调用refreshBody()让物理碰撞体匹配缩放后的视觉尺寸:
function create() { // ... 创建player和ball的代码 this.player.setScale(0.1, 0.1); this.player.refreshBody(); // 同步碰撞体 this.ball.setScale(0.1, 0.1); this.ball.refreshBody(); // 同步碰撞体 }
4. 修复全局变量问题(可选但建议)
将原本的全局按键变量改为场景局部变量,避免污染全局环境:
function create() { this.A = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.A); this.S = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.S); this.D = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.D); this.W = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.W); } // update中的按键判断需改为this.D.isDown这类形式
修复后的完整代码
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width"> <title>Soccer</title> <link href="style.css" rel="stylesheet" type="text/css" /> <script src="https://cdnjs.cloudflare.com/ajax/libs/phaser/3.16.2/phaser.min.js"></script> <script> function preload() { this.load.image('player', 'assets/player.png'); this.load.image("net", "assets/net.png"); this.load.image("ball", "assets/ball.png"); } function create() { // 改为场景局部变量 this.A = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.A); this.S = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.S); this.D = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.D); this.W = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.W); this.add.image(config.width - 100, config.height - 120, "net").setScale(0.2, 0.2); this.ball = this.physics.add.image(config.width / 2, config.height - 50, "ball").setScale(0.1, 0.1); this.ball.refreshBody(); // 同步碰撞体 this.player = this.physics.add.image(config.width / 4, config.height, 'player').setScale(0.1, 0.1); this.player.refreshBody(); // 同步碰撞体 this.ball.setBounce(1) this.player.setCollideWorldBounds(true); this.ball.setCollideWorldBounds(true); // 只创建一次碰撞器 this.physics.add.collider(this.ball, this.player); } function update() { let speed = 200; this.player.setVelocity(0); if (this.D.isDown) { this.player.setVelocityX(speed); } else if (this.A.isDown) { this.player.setVelocityX(-speed); } if (this.W.isDown) { this.player.setVelocityY(-speed); } } const config = { type: Phaser.AUTO, width: window.innerWidth, height: window.innerHeight, backgroundColor: '#000000', physics: { default: 'arcade', arcade: { gravity: { y: 100, }, debug: true } }, scene: { preload: preload, create: create, update: update } }; const game = new Phaser.Game(config); </script> </head> <body> </body> </html>
内容的提问来源于stack exchange,提问作者Koby K
相关产品推荐
相关产品推荐

