Phaser3 2D游戏炮弹抛物线射击实现问题求助
解决Phaser3中炮弹抛物线轨迹异常问题
问题原因分析
你当前的Phaser3代码通过固定速度值手动控制位置,还在达到阈值后反转竖直方向速度,这种逻辑不符合抛物线运动规律——真实抛物线中,水平方向速度恒定,竖直方向受重力持续加速(速度线性变化),或直接遵循二次函数位置关系(如你Unity代码中的实现),因此导致轨迹出现异常突变。
解决方案一:利用Phaser物理引擎实现(推荐)
Phaser的Arcade物理引擎已内置重力和速度处理,能自动生成自然的抛物线轨迹,无需手动计算位置:
import { ActorProps, ICollectable, IDieable, IMoveable } from "@games/common/interfaces"; import { Actor } from "@games/common/objects"; export default class Cannon extends Actor implements IMoveable, IDieable, ICollectable { declare body: Phaser.Physics.Arcade.Body; private isMoving: boolean; constructor(props: ActorProps) { super(props); this.scene.physics.add.existing(this); // 开启竖直方向重力(Phaser中y轴向下为正,重力值为正代表向下加速) this.body.setGravityY(300); // 设置初始速度:水平向左100,竖直向上200(负号对应Phaser中向上的方向) this.body.setVelocity(-100, -200); this.isMoving = true; } update(time: number, delta: number): void { if (this.isMoving) { // 自定义停止条件:比如炮弹回到初始高度以下时停止 if (this.y >= this.y + 500) { this.isMoving = false; this.body.setVelocity(0, 0); } } } die(): void {} move(): void {} collect(...props: any[]): void {} }
解决方案二:手动实现Unity式抛物线公式
如果需要完全自定义轨迹逻辑,可复刻你Unity中的二次函数计算方式:
import { ActorProps, ICollectable, IDieable, IMoveable } from "@games/common/interfaces"; import { Actor } from "@games/common/objects"; export default class Cannon extends Actor implements IMoveable, IDieable, ICollectable { declare body: Phaser.Physics.Arcade.Body; private currentX: number; private a: number = 0.001; // 抛物线弯曲系数,需根据游戏缩放调整(Phaser y轴向下,符号与Unity相反) private b: number = 0.5; // 轨迹倾斜系数 private c: number; // 初始y坐标 private speed: number = 100; // 水平移动速度 constructor(props: ActorProps) { super(props); this.scene.physics.add.existing(this); this.body.setAllowGravity(false); this.currentX = this.x; this.c = this.y; // 初始位置作为抛物线常数项 } update(time: number, delta: number): void { // 更新水平位置(向左移动) this.currentX -= this.speed * (delta / 1000); // 用二次函数计算竖直位置:y = a*(偏移量)^2 + b*(偏移量) + 初始y const offsetX = this.x - this.currentX; this.y = this.a * offsetX * offsetX + this.b * offsetX + this.c; // 自定义停止条件:比如向左移动500单位后停止 if (this.currentX <= this.x - 500) { this.currentX = this.x - 500; } } die(): void {} move(): void {} collect(...props: any[]): void {} }
说明
- 方案一依赖Phaser物理引擎,自动处理时间差、加速度等细节,还能无缝对接碰撞检测,稳定性更高。
- 方案二完全手动控制轨迹,适合需要高度自定义抛物线形状的场景,需调整
a、b、speed等参数匹配预期效果。
内容的提问来源于stack exchange,提问作者yunusemre agdin
相关产品推荐
相关产品推荐

