我正在开发一款游戏(并且已经问了几个问题),现在我还有一个问题要问你们。
此游戏中的关卡格式设置为 Uint16(我正在使用 SDL)的 tilemap,它们是 tilemapData 结构数组的索引。tilemapData 结构的位之一是 isConductive 位/布尔值。
该位的使用基本上是创建将各种对象连接在一起形成单个“powerNet”的路径。我在下面有一些关于当前方法的代码(它有效,但我会在之后解释为什么我真的讨厌它)
void findSetPoweredObjects(unsigned long x, unsigned long y, powerNetInfo * powerNet) {
//Look for poweredObjs on this tile and set their powerNet to the given powernet
for (int i = 0; i < level->numChunks[CHUNKTYPE_POWEREDDEF]; i++)
if (level->poweredObjects[i]->position[0] == x && level->poweredObjects[i]->position[1] == y)
level->poweredObjects[i]->powerNet = powerNet, powerNet->objectsInNet++;
}
void recursiveCheckTile(bool * isWalked, powerNetInfo * powerNet, unsigned long x, unsigned long y, tilemapData * levelMap) {
//If out of bounds, return
if (x < 0 || y < 0 || x >= level->mapDimensions[0] || y >= level->mapDimensions[1]) return;
//If tile already walked, return
if (isWalked[x + (y * level->mapDimensions[0])]) return;
//If tile is nonconductive, return
if (!(level->tiles[levelMap->map[x + (y * level->mapDimensions[0])]]->flags & TILETYPE_CONDUCTIVE)) return;
//Valid tile to check, see if there's a poweredobj on the tile (link it to the net if it is) and check the adjacent tiles.
isWalked[x + (y * level->mapDimensions[0])] = true;
findSetPoweredObjects(x,y,powerNet);
recursiveCheckTile(isWalked, powerNet, x - 1, y, levelMap);
recursiveCheckTile(isWalked, powerNet, x + 1, y, levelMap);
recursiveCheckTile(isWalked, powerNet, x, y - 1, levelMap);
recursiveCheckTile(isWalked, powerNet, x, y + 1, levelMap);
}
bool buildPowerNets(void) {
//Build the powernets used by the powered objects
//TODO: Rewrite buildPowerNets() & recursiveCheckTile() to avoid stack overflows and make it easier to backtrace powernets in-game
bool * isWalked;
isWalked = new bool[(level->mapDimensions[0] * level->mapDimensions[1])];
unsigned long x, y;
tilemapData * levelMap = level->layers[level->activeMap];
for (y = 0; y < level->mapDimensions[1]; y++) {
for (x = 0; x < level->mapDimensions[0]; x++) {
if (isWalked[x + (y * level->mapDimensions[0])]) continue;
isWalked[x + (y * level->mapDimensions[0])] = true;
if (level->tiles[levelMap->map[x + (y * level->mapDimensions[0])]]->flags & TILETYPE_CONDUCTIVE) {
//it's conductive, find out what it's connected to.
//But first, create a new powernet
powerNetInfo * powerNet = new powerNetInfo;
powerNet->objectsInNet = 0;
powerNet->producerId = -1;
powerNet->supplyType = POWER_OFF;
powerNet->prevSupplyType = POWER_OFF;
powerNet->powerFor = 0;
//Find adjacent tiles to this one, add them to it's powernet, and then mark them walked. Then repeat until the net is done.
recursiveCheckTile(isWalked, powerNet, x, y, levelMap);
}
}
}
delete isWalked;
for (int i = 0; i < level->numChunks[CHUNKTYPE_POWEREDDEF]; i++)
if (level->poweredObjects[i]->powerNet == NULL) return false;
return true;
}
请注意,返回 false 意味着函数失败(在这种情况下,它没有正确链接所有对象)。
我担心的是,由于堆栈溢出,在更复杂的地图上行走导电瓷砖的功能会完全失败。对于如何使用这些功能降低这种风险有什么想法?如果需要,我可以提供有关使用的结构的更多信息。
我考虑过修改代码,以便recursiveCheckTile
仅在到达交汇点时进行递归调用,否则只会交互地遵循其所在的导电路径,但这似乎仍然只是部分解决方案,因为我无法提前知道路径可能是多么扭曲或分支。
如果它有所作为,速度在这里完全不重要,因为这个函数只在地图被使用前处理时运行一次,所以使用一点额外的时间不会有什么坏处。