You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 20:40:11