cocos拖拽物体不同实现方式研究

第一种方式:

    onElMove(event:EventTouch){
        console.info("onMove");
        this.e1.setWorldPosition(event.getUILocation().x,event.getUILocation().y,0);
    }

这种方式有缺陷,因为当手指落下时,点击的位置不是Node的中心位置时,移动前会出现一个跳跃的行为,这种使得操作不连贯,效果很不好。

第二种方式: 通过偏移量(getUIDelta)来决定Node的位置,这种才是最好的方式 。

cc.Class({
    extends: cc.Component,
 
    start() {
        // 获取DragonBones实例
        this.dragonBonesNode = this.getComponent(cc.DragonBonesComponent);
        // 获取节点的collider组件
        this.collider = this.node.getComponent(cc.Collider);
        // 如果没有collider组件,则添加一个box collider
        if (!this.collider) {
            this.collider = this.node.addComponent(cc.BoxCollider);
        }
        // 注册触摸事件
        this.node.on(cc.Node.EventType.TOUCH_START, this.onTouchStart, this);
        this.node.on(cc.Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
        this.node.on(cc.Node.EventType.TOUCH_END, this.onTouchEnd, this);
    },
 
    onTouchStart(event) {
        // 记录开始触摸的位置
        this.startPos = event.getLocation();
    },
 
    //使用getDelta发现物体移动的没有手指移动的快。使用getUIDelta正常。
    onTouchMove(event) {
        console.info("onMove");
         // 计算移动的偏移量
        let delta = event.getUIDelta();

        this.newX = this.e1.position.x + delta.x;
        this.newY = this.e1.position.y +delta.y;

        
        // 更新节点位置
        this.e1.setPosition(this.newX,this.newY)
    },
 
    onTouchEnd(event) {
        // 触摸结束时可以处理一些事情
    },
 
    onDestroy() {
        // 清理注册的事件
        this.node.off(cc.Node.EventType.TOUCH_START, this.onTouchStart, this);
        this.node.off(cc.Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
        this.node.off(cc.Node.EventType.TOUCH_END, this.onTouchEnd, this);
    }
});

重点:要使用getUIDelta !!!

getDelta和getUIDelta有什么区别呢?全局与节点触摸和鼠标事件 API | Cocos Creator

这解释太拗口了,我是没读明白。

getDelta     获取触点距离上一次事件移动的距离对象,对象包含 x 和 y 属性。

getUIDelta  获取当前触点距离上一次触点移动在 UI 窗口内相对于左下角的距离对象,对象包含 x 和 y 属性。

### Cocos框架中实现拖拽俄罗斯方块功能 在Cocos框架中,实现拖拽俄罗斯方块的功能需要结合游戏逻辑与用户交互设计。以下是一个完整的实现思路和代码示例: #### 1. 游戏对象的定义 首先,需要定义俄罗斯方块的基本单元(Block)以及由多个单元组成的形状(Shape)。每个Block应具有位置、颜色等属性。 ```javascript // 定义Block类 class Block { constructor(x, y, color) { this.x = x; this.y = y; this.color = color; } } ``` #### 2. 拖拽功能的实现 为了实现拖拽功能,可以监听触摸事件,包括`onTouchStart`、`onTouchMove`和`onTouchEnd`。这些事件用于捕捉用户的触摸行为并更新方块的位置[^2]。 ```javascript // 定义拖拽逻辑 function enableDrag(blockNode) { let startX, startY; blockNode.on(cc.Event.TOUCH_START, (event) => { const touch = event.touch; const location = touch.getLocation(); startX = location.x; startY = location.y; }); blockNode.on(cc.Event.TOUCH_MOVE, (event) => { const touch = event.touch; const delta = touch.getDelta(); blockNode.x += delta.x; blockNode.y += delta.y; }); blockNode.on(cc.Event.TOUCH_END, (event) => { // 可在此处添加碰撞检测或落点校正逻辑 snapToGrid(blockNode); }); } // 网格对齐函数 function snapToGrid(node) { const gridWidth = 30; // 假设网格宽度为30像素 const gridHeight = 30; // 假设网格高度为30像素 node.x = Math.round(node.x / gridWidth) * gridWidth; node.y = Math.round(node.y / gridHeight) * gridHeight; } ``` #### 3. 碰撞检测与固定 当方块被拖拽到指定位置后,需要进行碰撞检测以确保其不会与其他已固定的方块重叠。如果发生碰撞,则将当前方块固定在当前位置,并生成新的方块。 ```javascript // 碰撞检测函数 function checkCollision(block, fixedBlocks) { for (let fixedBlock of fixedBlocks) { if (block.x === fixedBlock.x && block.y === fixedBlock.y) { return true; } } return false; } // 固定方块函数 function fixBlock(block, fixedBlocks) { fixedBlocks.push(block); } ``` #### 4. 游戏主循环 最后,在游戏主循环中更新所有活动方块的状态,并检查是否需要清除行或结束游戏。 ```javascript // 游戏主循环 function gameLoop(fixedBlocks) { for (let i = fixedBlocks.length - 1; i >= 0; i--) { if (checkRowComplete(fixedBlocks[i].y, fixedBlocks)) { clearRow(fixedBlocks[i].y, fixedBlocks); } } } // 检查某一行是否完整 function checkRowComplete(y, fixedBlocks) { let count = 0; for (let block of fixedBlocks) { if (block.y === y) { count++; } } return count >= 10; // 假设每行有10个方块 } // 清除某一行 function clearRow(y, fixedBlocks) { for (let i = fixedBlocks.length - 1; i >= 0; i--) { if (fixedBlocks[i].y === y) { fixedBlocks.splice(i, 1); } } } ``` ### 注意事项 - 在实际开发中,可能需要根据屏幕分辨率调整网格大小和方块初始位置。 - 拖拽过程中,建议增加视觉反馈(如高亮显示目标网格)以提升用户体验[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值