2013-07-25 220 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 –