2014-09-29 51 views
0

好的,所以今天我決定嘗試進一步優化我的平鋪引擎的碰撞檢測代碼。平鋪引擎碰撞優化

這就是我所做的:

Circle類檢查是否有範圍內的點。如果有,則檢查玩家與平鋪之間的碰撞。

代碼:

 int tileWidth = 128; 
     int tileHeight = 128; 

     int[,] Layer3 = { 1, 1, 1, etc... }; 

     int tileMapWidth = Layer3.GetLength(1); 
     int tileMapHeight = Layer3.GetLength(0); 

     Rectangle tile, tile2; 

     for (int x = 0; x < tileMapWidth; x++) 
     { 
      for (int y = 0; y < tileMapHeight; y++) 
      { 
       int wallIndex = Layer3[y, x]; 

       if (wallIndex == 1) //Full-sized Tile Collision (128 x 128) 
       { 
        if (collisionCircle.Contains(new Vector2(x * tileWidth + (tileWidth/2) + (int)Player.camera.Position.X, 
                  y * tileHeight + (tileHeight/2) + (int)Player.camera.Position.Y))) //+ tile/2 is for centering the point 
        { 
         tile = new Rectangle(x * tileWidth + (int)Player.camera.Position.X, y * tileHeight + (int)Player.camera.Position.Y, tileWidth, tileHeight); 
         Collide(tile); 
        } 
       } 
      } 
     } 

這將檢查整個三層如果有一個 「1」。如果有,則指定矩形,並在碰撞半徑內檢查碰撞。

此外,我檢查了這個代碼(用繪圖方法),我知道它工作正常,至少是行爲。

我添加了大約120,000(32 x 3888)的圖塊,試圖使它滯後,並且在代碼之前,它有一點點滯後。但是在我加入代碼之後,它就更加落後了。

我認爲,因爲它是隻檢查是半徑不會甚至遠程滯後內的地磚(點)之間的碰撞,但事實並非如此......

任何幫助/如何思路優化這將是偉大的。

非常感謝, Shyy

編輯:

Cirlce.Contains()代碼:

public bool Contains(Vector2 Point) 
    { 
     return ((Point - position).Length() <= radius); 
    } 

我用了一個圓,因爲我聽說它比使用矩形更快。

+1

嘗試用矩形進行預測試,尤其是如果你的圈測試使用sqrt而不是比較平方距離 – LearnCocos2D 2014-09-29 08:04:38

+0

@Cocos,謝謝你的回覆。我上面發佈了我的Circle.Contains()代碼。我只使用一個圓圈,因爲我聽說它比使用矩形快。 – 2014-09-29 14:38:27

+0

你從哪裏聽到的?如果您比較長度的平方,那麼它的性能只與性能相當,但由於您使用的是Length(),這意味着使用平方根使其變慢。查看@OSborn的答案。 – LearnCocos2D 2014-09-30 09:37:25

回答

1

另一個可能的優化是不是 return ((Point - position).Length() <= radius); 使用 return ((Point - position).LengthSquared() <= radius * radius);

這是更快,因爲Vector2.Length()所必須進行昂貴的平方根運算。 Vector2.LengthSquared()不必執行那個緩慢的操作。半徑必須乘以它自己以考慮從矢量被平方的長度。

這聽起來像你正在試圖確定你不需要使用什麼瓷磚與玩家碰撞。你可以做的另一個優化是,如果在(X = 5,Y = 5)的區域位於玩家的左上方,那麼你不需要在(X = 4,Y = 4) 。類似地,如果(X = 5,Y = 5)低於和向右,則(X = 6,Y = 6)保證太遠。嘗試確定何時通過了播放器,而不再需要檢查碰撞。

+0

謝謝你的回覆,Osborn。我會盡快實施!至於第二部分,這就是爲什麼圈子正在檢查點以查看範圍內是否有瓦片。雖然我意識到我只是通過這樣做加入了另一次碰撞檢查,這可能是爲什麼仍然存在性能問題。 – 2014-09-29 20:08:43

0

我建議只循環使用屏幕上的可見圖塊來檢查使用運動偏移量的碰撞。 我會試着從我的腦袋東西..

for x as integer = 0 + offSetX to tilesInWidth + offSetX 
    for y as integer = 0 + offSetY to tilesInHeight + offSetY 
     if player.insideCircle(player.position, radius) ' 
     object = layer(y,x); 
     if player.collideWith(object) then Collide() 
     end if 
    next 
next 
+0

啊,好的。我明白你說的是什麼,雖然我在Visual Basic中不太流利。一些簡單的問題:offSetX/Y應該代表什麼?我假設tilesInWidth/Height是地圖中的圖塊數量?謝謝您的幫助。 – 2014-09-29 14:41:50

+0

哦,我剛剛意識到一些事情。我的瓷磚地圖中會有實體(怪物/生物)。所以我不確定是否只檢查屏幕上的矩形將是一個好主意......看起來好像它們能夠在牆壁上發生故障。或者像你說的那樣做是個好主意,但是如果可能的話,是否要單獨檢查實體?謝謝。 – 2014-09-29 16:48:23