如何在Phaser.js Arcade Physics中拖拽物理组子元素并保留碰撞?
用Arcade Physics实现物理组内元素的拖拽+碰撞保留方案
Arcade Physics本身没有内置拖拽API,setDraggable是Matter.js专属方法,得手动通过输入事件实现拖拽逻辑,同时保留碰撞效果,具体实现如下:
核心思路
通过监听鼠标/触摸事件,临时接管拖拽中物体的位置控制,拖拽结束后交还控制权给物理引擎,全程不关闭碰撞体,确保碰撞效果正常生效。
代码实现
假设你已经在场景中创建了this.photons物理组,直接在create方法中添加以下逻辑:
// 初始化拖拽追踪变量 let draggingPhoton = null; // 1. 监听鼠标按下:识别要拖拽的组内元素 this.input.on('pointerdown', (pointer) => { // 检测点击位置是否命中photons组内的元素 const target = this.physics.overlapPointer(pointer, this.photons); if (target) { draggingPhoton = target; // 临时清除物体的速度和加速度,避免拖拽时物理引擎干扰 draggingPhoton.setVelocity(0, 0); draggingPhoton.setAcceleration(0, 0); // 如果物体受重力影响,临时关闭重力 draggingPhoton.setGravityY(0); } }); // 2. 监听鼠标移动:实时更新拖拽元素的位置 this.input.on('pointermove', (pointer) => { if (draggingPhoton) { // 使用世界坐标确保适配相机缩放/偏移 draggingPhoton.x = pointer.worldX; draggingPhoton.y = pointer.worldY; } }); // 3. 监听鼠标抬起:结束拖拽,恢复物理行为 this.input.on('pointerup', () => { if (draggingPhoton) { // 恢复重力(如果之前关闭过) draggingPhoton.setGravityY(1); draggingPhoton = null; } });
关键注意事项
- 碰撞保留:全程未禁用物体碰撞体,组内元素和其他组/自身的碰撞会正常触发,无需额外配置。
- 坐标适配:必须使用
pointer.worldX和pointer.worldY,否则场景有相机缩放或移动时,拖拽位置会偏移。 - 体验优化:如果需要更平滑的拖拽,可在
pointermove中添加缓动逻辑,比如draggingPhoton.x += (pointer.worldX - draggingPhoton.x) * 0.1。 - 多触摸支持:上述逻辑兼容移动端触摸输入,Phaser的
pointer事件已适配触摸操作。
内容的提问来源于stack exchange,提问作者Vatsa Pandey
相关产品推荐
相关产品推荐

