V7投稿|控制物体移动轨迹

引擎:CocosCreator 3.8.2

思考了很久决定要不要发这票文章。因为毕竟我也是一个新手。但是这个问题真的困扰了我很久。
image
特意分享给大家。
如图所示有2个方块。他们可以跟着轨迹移动。
这个轨迹箱子总体来说有以下几个规则。
1.只能沿着轨迹移动。
2.上面只能有一个物体。
3.如果有2个物体不可以移动。
4.不可以穿越其他方块。包括自己的同类。

在我架构游戏的时候,把cocos的物理系统想象得太完美了。
结果就是一坨屎。我这个2d平面游戏还不如不用物理系统。就用2维数组来解决移动的问题可能还会比较好。
但是我游戏都开发到一半了。我真的很想重构游戏。不用物理系统了。
我再b站演示了所有遇到的bug。
https://www.bilibili.com/video/BV1QZ421y73i/?vd_source=5cd2641242f2c82d2c31a86639f999a6
最后我提出了一个解决方案。就是最原始的方法,也最笨。
1.image 根据每种方块建立一个规则。比如这个就只能从中间往下移动。

switch (range.grid) {
case 11:
// 只能沿x轴(左右)移动
restriction = {
xRange: [(xPixelStart + xPixelEnd) / 2, xPixelEnd],
yRange: [yPixelStart, yPixelEnd],
pathType: ‘center-to-right’, // 从中心点到最右边
};
break;
case 12:
// 可以沿x轴(左右)移动,如果在中心点也可以往下移动
restriction = {
xRange: [xPixelStart, xPixelEnd],
yRange: [yPixelStart, yPixelEnd],
pathType: ‘T-shaped’, // 特殊的T形路径,可能需要特别处理。
};
break;
。。。。。。

2.限制他们的移动范围。有的只能移动X。有的只能移动Y。
3.由于每一关都是变化的。所以需要每一关都计算移动范围。这里我使用了一个公式。
image 找到可移动方块,然后像四周扩散。寻找这四个方向的方块是不是轨迹如果是轨迹则包含到轨迹数组里面。因为方块必须需要到某个为止才会计算这个位置的移动范围。所以我并不需要担心,这个轨迹是不是属于这个移动方块的。(ps.这样想起来我似乎可以提前把这些方块放进一个数组,就不需要这样来找了。 :rofl:
代码如下:

    // 探索 guidao 层
    const exploreGuidao = (x: number, y: number) => {
        // 检查坐标是否在图层边界内
        if (x < 0 || y < 0 || x >= layerSize.width || y >= layerSize.height) {
            return; // 超出边界,直接返回
        }
        const key = `${x},${y}`;
        if (visited.has(key)) return; // 如果已访问过,直接返回
        visited.add(key); // 标记为已访问
        const tile = guidaoLayer.getTiledTileAt(x, y, true);
        if (tile && tile.grid != 0) {
            movableRanges.push({ x, y, grid: tile.grid });
            // 继续探索四个方向
            exploreGuidao(x - 1, y);
            exploreGuidao(x + 1, y);
            exploreGuidao(x, y - 1);
            exploreGuidao(x, y + 1);
        }
    };

    // 遍历 move 层以找到起始点
    for (let x = 0; x < layerSize.width; x++) {
        for (let y = 0; y < layerSize.height; y++) {
            const tile = moveLayer.getTiledTileAt(x, y, true);
            if (tile && tile.grid != 0) {
                // 从 move 方块的位置开始探索 guidao
                exploreGuidao(x, y);
                // 在发现 move 方块后创建 movableBoxNode
                const movableBoxNode = instantiate(this.movableBoxPrefab);
                const adjustedY = layerSize.height - y - 1; // 可能需要根据你的坐标系调整
                const position = new Vec3(x * tileSize.width + offsetX, adjustedY * tileSize.height + offsetY, 0);
                movableBoxNode.setPosition(position);
                this.node.addChild(movableBoxNode); // 将新创建的节点添加到场景中

                const moveKey = `move${x}_${y}`;
                this.spritesInfo[moveKey] = {
                    node: movableBoxNode,
                    position: position,
                    active: movableBoxNode.active
                };
                const grass = movableBoxNode.getComponent(Grass);
                // 计算移动范围并打印结果
                // console.log("移动范围:", movableRanges);
                const movementRange = grass.calculateMovementRange(movableRanges, layerSize, tileSize);
                // console.log("移动范围:", movementRange);
            }else {
                // 瓦片不存在,删除这个节点
                if (tile.node) tile.node.removeFromParent();
            }
        }
    }

计算边界的函数很简单因为每个方块都是64*64的,基本一看就能懂。

calculateGlobalBounds(movementRestrictions: { x: number, y: number, grid: number, restriction: any }[]) {
let xMin = Infinity;
let xMax = -Infinity;
let yMin = Infinity;
let yMax = -Infinity;

    movementRestrictions.forEach(restriction => {
        xMin = Math.min(xMin, restriction.restriction.xRange[0]);
        xMax = Math.max(xMax, restriction.restriction.xRange[1]);
        yMin = Math.min(yMin, restriction.restriction.yRange[0]);
        yMax = Math.max(yMax, restriction.restriction.yRange[1]);
    });

    this.globalBounds = { xMin, xMax, yMin, yMax };
}

这期就讲到这里。判断可移动方块上面是否有重物。我使用了一个更笨的方法。这一期就暂时不讲了。
大家如果想要体验我做的游戏是否丝滑。可以扫码试试看。微信小游戏贪吃的方块。
不过要玩到21关才会出现这个逻辑。当然也可以去b站看我的视频讲解。不过我怕别人看不懂。我再b站基本不讲代码。
gh_06bce309d886_1280

如果大家有更好的办法,请务必告诉我。因为我用iphone8玩游戏的时候是真的会卡。 :sweat_smile:

4赞

支持一下 !

Mark~

看了你最近发的很多文章,也看了你在B站的视频,说说我的想法,仅供参考。

1.这个游戏完全没必要使用物理(仅限该游戏在steam上展示的游戏内容),你的想法是对的,用2维数组会更加方便和简洁。至于你说游戏开发一半了,这个游戏的代码量本来不大,重构完全可以。方块下落使用简单的物理公式模拟一下。抛开物理模块,你的包体变小,不需要碰撞检测,性能也会提升。

  1. 针对关卡,给不同的方块添加不同的tag,0:空气 1:墙体 2:轨道。每个方块拥有自己的坐标,通过坐标获取当前位置。根据你滑块当前的坐标,检查一下横竖两个方向上所有tag=2的连续块的位置并且该位置没有滑块,轨道的范围就有了,同时也解决了不能穿越同类的问题。滑块移动的判断更简单了,滑块坐标y - 1和y-2的位置上如果都有其他方块那就是不能移动,只有y-1的位置上有就可以移动。如下图所示,
    map

  2. 这一点不是针对你游戏的。我看了你第一个视频里,是用ChatGpt在生产代码和图片,很明显提高了生产效率,很不错的方向。但是如果你打算以后从事这方面的工作,而你又是一个新手(老鸟请随意),那么你还是应该手搓代码,用gpt生成素材。如果你只是想借助AI蹭一蹭游戏的边,然后完全不打算往这个方向发展,那无所谓,怎么快怎么来。

以上,个人看法,并不是最优解,欢迎讨论。

1赞

谢谢大佬的回复。就这么滴吧。主要是前期架构没有想好久开始做了。以为物理引擎很好使。结果可能用力过猛了。

:+1: :+1: