小马589 2024-07-04 02:42 采纳率: 50%
浏览 109
已结题

Cocos creator缓动问题

我用的cocos creator 3.6 (用的语言是ts,软件是VS Code)
我做了一个类似羊了个羊的游戏。
在这过程中点击动画遇到了一个位移问题。
先看羊了个羊的动画,
当我们正常速度点击:
点击第三张(小草)会到下方的第三格的位置,点击第四张(玉米)会跟到玉米1后面然后两张小草依次后移1格位置。

img

再看快速点击(也就是第三张在移动的过程中点击第四张)
点击第三张(小草)在移动到第三格位置的过程中,立马点击第四张(玉米),小草2的路径发生了改变,会自动跑到第四格的位置,玉米2会跟在第一张玉米后面.小草1会向右移动一格位置。

img

再看我做的,正常速度点击是没有问题的

img

但是快速点击问题就出来了。
点击第三张(葡萄)在移动到第三格位置的过程中,立马点击第四张(草莓),葡萄2的路径发生了改变,会自动跑到第四格的位置,但是他又回到第三格位置和向右移动一格的葡萄1重叠了。我接着说一下我的代码逻辑,麻烦看看怎么解决

img

这个砖块是预制体,预制体上面的图案是随机的生成的。
上方区域(A区域)的是实例化到指定位置的预制体
点击上方的砖块,A区域下面的这个砖块节点会被删除,但是删除前获得了这个坐标的位置。然后把这个位置转化为世界坐标;再转化成下方区域(B区域)的节点坐标,接着位移到下方。意思就是先在B实例化出来然后移到B对应的位置。下方我做了个刷新的逻辑,如果砖块相同,他就会到前一块相同的后方,后面所有的砖块位置+1。实例化出来到下方的位置我用了个tween .to .call的方法。我不知道是刷新的问题还是这个缓动做的不对。本人不太懂,不知道描述的也没有问题,如果还需要描述哪些信息请告知

  • 写回答

21条回答 默认 最新

  • 专家-赤兔[在线] 优质创作者: 编程框架技术领域 2024-07-04 08:29
    关注

    引自免费微信小程序:皆我百晓生

    要解决这个问题,首先确保你的动画或位移逻辑不会因为快速连续的点击而混乱。看起来问题出在当一个砖块正在移动时,如果立即点击另一个砖块,会导致移动中的砖块路径发生错误的调整。这里是一个可能的解决方案思路,以及如何调整你的代码逻辑以避免这种情况。

    1. 管理动画状态

    首先,你需要一个机制来跟踪每个砖块是否正在移动。这可以通过为每个砖块添加一个布尔属性 isMoving 来实现。

    class Brick extends cc.Component {
        isMoving: boolean = false;
    }
    

    2. 队列移动请求

    当用户点击砖块时,不立即执行移动操作,而是将移动请求放入一个队列。这样,即使连续快速点击,也能确保所有操作按顺序执行。

    let moveQueue: {brick: Brick, targetPos: cc.Vec2}[] = [];
    
    function queueMove(brick: Brick, targetPos: cc.Vec2) {
        if (!brick.isMoving) {
            brick.isMoving = true;
            moveQueue.push({brick, targetPos});
            executeNextMove();
        }
    }
    
    function executeNextMove() {
        if (moveQueue.length > 0) {
            let {brick, targetPos} = moveQueue.shift();
            cc.tween(brick.node)
                .to(1, {position: targetPos}, {easing: 'linear'})
                .call(() => {
                    brick.isMoving = false;
                    // 检查并执行下一个移动
                    executeNextMove();
                })
                .start();
        }
    }
    

    3. 刷新逻辑调整

    在移动完成后(即在.call()回调内),根据当前B区域的状态更新砖块位置。确保在处理新砖块之前,所有已有的砖块已经完成了它们的移动,并且更新逻辑正确处理了砖块的排列顺序。

    4. 实例化逻辑

    在实例化新砖块到B区域时,直接将其位置设置为目标初始位置(即未考虑排序前的位置),然后通过调用queueMove来处理移动和排序,而不是立即执行位移。

    完整示例代码片段

    // 假设你有一个函数处理砖块的点击事件
    function onBrickClicked(brick: Brick, targetPositionInB: cc.Vec2) {
        // 将移动操作加入队列
        queueMove(brick, targetPositionInB);
        
        // 其它点击处理逻辑,比如删除A区域的节点等
    }
    
    // 调整B区域内部砖块位置的逻辑应确保在所有移动完成后再进行
    function refreshBrickPositions() {
        // 这里实现具体的逻辑,比如遍历B区域的所有砖块,根据类型重新排序
    }
    

    注意事项

    • 确保在所有移动动画结束后才进行位置刷新,避免在移动过程中修改目标位置导致动画混乱。
    • 使用队列管理移动请求可以确保动作序列化执行,避免并发冲突。
    • 考虑到性能,对于大量砖块的移动,可能需要优化处理队列的方式,例如限制同时进行的移动数量。

    通过这种方式,你应该能解决快速点击时的位移异常问题。如果有其他细节或代码部分需要具体帮助,请提供更详细的代码片段或描述。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(20条)

报告相同问题?

问题事件

  • 系统已结题 7月13日
  • 已采纳回答 7月5日
  • 创建了问题 7月4日