2013-07-25 190 views
2

所以我在游戏中使用Box2D进行碰撞检测。我有一个包含地形信息的地图:现在它只是一个char [] [],它具有道路或草地。现在,在每个关卡开始时,我都想创建矩形来描述不同的地形,但是我希望这些矩形得到优化,显然这需要相当多的算法。Box2D中的碰撞检测

我的第一种方法是在关卡开始时为地图上的每块拼贴创建一个单独的地形。 FPS减少到5.

我的第二个想法是当玩家沿着地图移动时,为地形创建不同的矩形,删除不可见的矩形。虽然它仍然是很多矩形,但会少得多。

我还没有尝试第二种方法,但我想知道:有没有什么简单的方法可以让我有效地对大块地形地形进行碰撞检测?

谢谢。

+0

多大的tilemap的?我做了1000x1000的瓷砖。 –

+0

只需在Box2D中一次添加它们全部?哇,这很令人印象深刻。我正在使用可怜的100x100。 – helsont

+0

您可以使用形状类的重叠方法。这不是它所称的,但我忘记了它的名字。它在javadoc的形状。 –

回答

4

尝试组合瓷砖。举例来说,如果你有16个区块,像这样的16分矩形碰撞体...

* * * * 
* * * * 
* * * * 
* * * * 

您可以将这些瓷砖明显合并成一个大的矩形。

现在,事情变得更加困难,如果你在一个奇怪的安排有瓷砖,也许是这样的...

**--- 
****- 
*--** 
-*-*- 

我刚刚使用quad treesweep 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); 
    } 
} 
+0

所以我在这之前做了一些关于四叉树的研究(我也想实现放大/缩小功能),并且我对如何使用扫描和修剪来创建矩形有点困惑。扫描和修剪似乎适用于碰撞检测,我不希望这些矩形重叠。当你在你的问题中发布时,它们将会相邻。我在这里错过了什么? – helsont

+0

运行四叉树后,您将有一堆矩形。这些矩形都不会重叠,但有些会相邻。 Sweep和Prune通过X轴对矩形进行排序,然后对Y轴进行排序以快速确定矩形是否发生碰撞。你可以做同样的事情来快速确定矩形是否相邻(如果它们共享边缘)。这就是我的意思。按X和y值对QuadTree输出进行排序,以便您只更快速地比较相邻的矩形。 –

+0

我已经发布了我的扫描和修剪代码。我有一些东西在那里,这很奇怪,例如我缓存矩形,以防止产生垃圾(不必要,因为这将只做一次,而不是重复)。现在我已经为你做了大约50%的工作: )。只需实现四叉树,你就是免费的! @ user1264811 –