所以我在游戏中使用Box2D进行碰撞检测。我有一个包含地形信息的tilemap:现在它只是一个char [] [],有道路或草地。现在,在每个级别的开始,我想创建矩形来描述不同的地形,但我希望这些矩形得到优化,显然需要相当多的算法。
我的第一个方法是在关卡开始时为地图中的每个图块创建一个单独的地形。 FPS降至5。
我的第二个想法是当玩家沿着地图移动时,简单地为地形创建不同的矩形,删除不在视野中的矩形。虽然它仍然会有很多矩形,但它会少得多。
我还没有尝试过第二种方法,但我想知道:对于使用大型tilemap有效地对地形进行碰撞检测,有什么简单的方法吗?
感谢。
答案 0 :(得分:4)
尝试组合图块。例如,如果您有16个矩形碰撞体积用于16个瓷砖,那么......
* * * *
* * * *
* * * *
* * * *
显然,您可以将这些图块组合成一个大矩形。
现在,如果你有一个奇怪的安排瓷砖,事情变得更加困难,也许就像这样......
**---
****-
*--**
-*-*-
我刚刚在游戏中使用quad tree和sweep and prune解决了这个问题。 (扫描和修剪不是绝对必要的,它是一种优化。)
Quad tree将您的方块分割为更大的矩形,然后迭代四叉树生成的矩形,如果它们具有相同的宽度,则将它们组合,然后再次迭代它们并将它们组合成类似的高度。重复,直到你不能再组合它们,然后生成碰撞体积。
Here's a link to a question我问过一个更优化的减少。我可能不会实现这个,因为听起来很困难,而且我目前的方法运作良好。
一些代码:
do {
lastCompressSize = currentOutput;
this.runHorizontalCompression(this.output1, this.output2);
this.output1.clear();
this.runVerticalCompression(this.output2, this.output1);
this.output2.clear();
currentOutput = this.output1.size;
iterations += 1;
}while (lastCompressSize > currentOutput);
public void runHorizontalCompression(Array<SimpleRect> input,
Array<SimpleRect> output) {
input.sort(this.xAxisSort);
int x2 = -1;
final SimpleRect newRect = this.rectCache.retreive();
for (int i = 0; i < input.size; i++) {
SimpleRect r1 = input.get(i);
newRect.set(r1);
x2 = newRect.x + newRect.width;
for (int j = i + 1; j < input.size; j++) {
SimpleRect r2 = input.get(j);
if (x2 == r2.x && r2.y == newRect.y
&& r2.height == newRect.height) {
newRect.width += r2.width;
x2 = newRect.x + newRect.width;
input.removeIndex(j);
j -= 1;
} else if (x2 < r2.x)
break;
}
SimpleRect temp = this.rectCache.retreive().set(newRect);
output.add(temp);
}
}
public void runVerticalCompression(Array<SimpleRect> input,
Array<SimpleRect> output) {
input.sort(this.yAxisSort);
int y2 = -1;
final SimpleRect newRect = this.rectCache.retreive();
for (int i = 0; i < input.size; i++) {
SimpleRect r1 = input.get(i);
newRect.set(r1);
y2 = newRect.y + newRect.height;
for (int j = i + 1; j < input.size; j++) {
SimpleRect r2 = input.get(j);
if (y2 == r2.y && r2.x == newRect.x
&& r2.width == newRect.width) {
newRect.height += r2.height;
y2 = newRect.y + newRect.height;
input.removeIndex(j);
j -= 1;
} else if (y2 < r2.y)
break;
}
SimpleRect temp = this.rectCache.retreive().set(newRect);
output.add(temp);
}
}