2013-09-16 28 views
2

我一直在爲一個學校項目開發我自己的物理引擎,最近我遇到了一個問題:每個像素在大精靈上的碰撞使我的FPS下降很多。每像素碰撞的優化

這是我的像素碰撞代碼。在輸入下面的代碼之前,我使用Intersects()來查看它們的包圍盒是否發生碰撞。

private bool PerPixelCollision(IObject a, IObject b) 
{ 

    Color[] bitsA = new Color[a.Texture.Width * a.Texture.Height]; 
    a.Texture.GetData(bitsA); 
    Color[] bitsB = new Color[b.Texture.Width * b.Texture.Height]; 
    b.Texture.GetData(bitsB); 

    // Calculate the intersecting rectangle 
    int x1 = Math.Max(a.Bounds.X, b.Bounds.X); 
    int x2 = Math.Min(a.Bounds.X + a.Bounds.Width, b.Bounds.X + b.Bounds.Width); 

    int y1 = Math.Max(a.Bounds.Y, b.Bounds.Y); 
    int y2 = Math.Min(a.Bounds.Y + a.Bounds.Height, b.Bounds.Y + b.Bounds.Height); 

    Color c; 
    Color d; 
    // For each single pixel in the intersecting rectangle 
    for (int y = y1; y < y2; ++y) 
    { 
     for (int x = x1; x < x2; ++x) 
     { 
      // Get the color from each texture 
      c = bitsA[(x - a.Bounds.X) + (y - a.Bounds.Y) * a.Texture.Width]; 
      d = bitsB[(x - b.Bounds.X) + (y - b.Bounds.Y) * b.Texture.Width]; 

      if (c.A != 0 && d.A != 0) // If both colors are not transparent (the alpha channel is not 0), then there is a collision 
      { 
       return true; 
      } 
     } 
    } 
    // If no collision occurred by now, we're clear. 
    return false; 
} 

在我用來測試的例子中,我在另一個代表地板(736x79)的精靈中放了4個精靈。當我將代表地板的精靈更改爲更大的精靈(3600x270)時,FPS會下降。我知道這個問題出現在像素碰撞中,因爲我正在使用探查器。

有沒有人有任何想法如何優化碰撞?

P.S .:對不起,如果我不清楚我的問題。我的英文不是很好。

編輯:第一個問題是通過使用@pinckerman提供的解決方案解決的,但我發現另一個與像素碰撞檢測有關。 當一個精靈與一個紋理的透明部分碰撞時,我們得到相交的部分並檢查該部分的所有像素。問題是:當透明部分足夠大以覆蓋整個精靈時,我會檢查該精靈的整個紋理(當前使用的是50x50像素,即2500像素)。有沒有辦法不檢查整個紋理?

感謝

+2

我不是專家,但我不認爲你應該對像地板這樣的東西進行像素碰撞檢查。如果你想要地形碰撞做某種多邊形碰撞檢查。或者如果地板只是平坦的做一個矩形甚至一個線路交叉口檢查。對不起,但我無法幫助您優化您的算法。 –

+0

不要使用這個。這是殺人兇手。使用線,框,圓,多邊形碰撞。或者全部組合在一起,但不是像素碰撞。這只是浪費資源。 –

+0

我覺得有必要給我的人羣添加我的聲音,並指出你正在遇到性能問題,從事這種碰撞檢測。在紋理上調用'GetData()'會安裝渲染pipeline_,這將阻止GPU和CPU以最高效率一起工作。在大多數情況下,使用幾何碰撞檢測會更好 - 儘管當然這種學習練習沒有任何問題。有關更多信息,請參閱[本文](http://blogs.msdn.com/b/shawnhar/archive/2008/04/14/stalling-the-pipeline.aspx)。 –

回答

2

我敢肯定,你的FPS下降這麼多,因爲你在你的方法開始做

Color[] bitsA = new Color[a.Texture.Width * a.Texture.Height]; 
a.Texture.GetData(bitsA); 
Color[] bitsB = new Color[b.Texture.Width * b.Texture.Height]; 
b.Texture.GetData(bitsB); 


我想你每Update循環調用你的PerPixelCollision,並且在每個遊戲週期創建和應付數百萬個值,這不是一件非常有效的事情。

一個巨大的精靈創建了一個巨大的Color[]數組:數組越大,這個方法越慢。

編輯:

對於你的第二個問題,我認爲,如果你不事先知道哪裏是你的「大」質感的透明區域,你無論如何都要檢查整個精靈。
如果你的精靈不是太大,不會浪費太多性能。 PS:我看到你自己得到相交Rectangle,也許你可以找到有用的this method

+2

不僅需要創建數組,垃圾收集器必須稍後再清理它們。切勿在每幀都調用的代碼中創建數組,如果可能的話! –

+0

@ColeCampbell完全同意。 – pinckerman

+0

謝謝@pinckerman!問題解決了:)但我發現了另一個x.x.請閱讀 –