引擎:CocosCreator 3.8.2
思考了很久决定要不要发这票文章。因为毕竟我也是一个新手。但是这个问题真的困扰了我很久。
特意分享给大家。
如图所示有2个方块。他们可以跟着轨迹移动。
这个轨迹箱子总体来说有以下几个规则。
1.只能沿着轨迹移动。
2.上面只能有一个物体。
3.如果有2个物体不可以移动。
4.不可以穿越其他方块。包括自己的同类。
在我架构游戏的时候,把cocos的物理系统想象得太完美了。
结果就是一坨屎。我这个2d平面游戏还不如不用物理系统。就用2维数组来解决移动的问题可能还会比较好。
但是我游戏都开发到一半了。我真的很想重构游戏。不用物理系统了。
我再b站演示了所有遇到的bug。
https://www.bilibili.com/video/BV1QZ421y73i/?vd_source=5cd2641242f2c82d2c31a86639f999a6
最后我提出了一个解决方案。就是最原始的方法,也最笨。
1. 根据每种方块建立一个规则。比如这个就只能从中间往下移动。
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.由于每一关都是变化的。所以需要每一关都计算移动范围。这里我使用了一个公式。
找到可移动方块,然后像四周扩散。寻找这四个方向的方块是不是轨迹如果是轨迹则包含到轨迹数组里面。因为方块必须需要到某个为止才会计算这个位置的移动范围。所以我并不需要担心,这个轨迹是不是属于这个移动方块的。(ps.这样想起来我似乎可以提前把这些方块放进一个数组,就不需要这样来找了。 )
代码如下:
// 探索 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站基本不讲代码。
如果大家有更好的办法,请务必告诉我。因为我用iphone8玩游戏的时候是真的会卡。