2013-11-02 40 views
3

更新; -changing j = 0 to j = i允許多達700個具有平滑幀速率的粒子2D粒子引擎無法處理超過450個粒子。爲什麼? (XNA)

我試圖用數百個具有Vector2s的粒子聲明其位置和Vector2的速度來模擬2D水。

談到碰撞檢測,我的程序不喜歡有超過450個粒子,儘管只使用了畢達哥拉斯定理。

這裏是主類中的碰撞檢測;

 for (int i = 0; i < particleList.Count; i++) 
      { 
       for (int j = 0; j < particleList.Count; j++) 
       { 
        if (distanceBetween(particleList[i].position, particleList[j].position) < reactDistance) 
        { 
         if (particleList[i].position.X > particleList[j].position.X) //x axis 
         { 
          particleList[i].velocity.X += repelSpeed; 
          particleList[j].velocity.X -= repelSpeed; 

          particleList[i].position.X -= attractSpeed; 
          particleList[j].position.X += attractSpeed; 
         } 
         else 
         { 
          particleList[i].velocity.X -= repelSpeed; 
          particleList[j].velocity.X += repelSpeed; 

          particleList[i].position.X += attractSpeed; 
          particleList[j].position.X -= attractSpeed; 
         } 

         if (particleList[i].position.Y > particleList[j].position.Y) //y axis 
         { 
          particleList[i].velocity.Y += repelSpeed; 
          particleList[j].velocity.Y -= repelSpeed; 

          particleList[i].position.Y -= attractSpeed; 
          particleList[j].position.Y += attractSpeed; 
         } 
         else 
         { 
          particleList[i].velocity.Y -= repelSpeed; 
          particleList[j].velocity.Y += repelSpeed; 

          particleList[i].position.Y += attractSpeed; 
          particleList[j].position.Y -= attractSpeed; 
         } 
        } 
       } 
      } 

這裏是distanceBetween(v1,v2)方法;

 public float distanceBetween(Vector2 a, Vector2 b) 
    { 
     float xDist, yDist, distTo; 
     if (a.X > b.X) //x axis 
     { 
      xDist = a.X - b.X; 
     } 
     else 
     { 
      xDist = b.X - a.X; 
     } 

     if (a.Y > b.Y) //y axis 
     { 
      yDist = a.Y - b.Y; 
     } 
     else 
     { 
      yDist = b.Y - a.Y; 
     } 
     distTo = (float)(Math.Sqrt((xDist * xDist) + (yDist * yDist))); 
     return distTo; 
    } 

Vector2.Distance(v1,v2)不會產生可見的性能變化。

如果你想知道地球上吸引什麼,這是我試圖形成水收集的可憐嘗試。我不知道該怎麼做。

最後,我想是這樣的:http://grantkot.com/MPM/Liquid.html

+1

由於第一個循環粒子已經被檢查不能第二個循環開始爲j = i而不是j = 0? –

+0

哇,你說得對。該程序現在允許多達700個具有平滑幀速率的粒子! – ShadowByte

+1

你也可以嘗試同時做到這一點。 http://msdn.microsoft.com/en-us/library/system.threading.tasks.parallel.aspx – Lasse

回答

2

雖然有可以改善的一些性能方面,最終,它是將大大超過任何努力顆粒的存儲。

對於每個粒子,您的算法是O(n^2),您將再次遍歷整個粒子列表。對於n = 700,即700*700 = 490000循環的執行。此外,太多的粒子檢查i。如果你在j=i開始內循環,你將會獲得明顯的加速。

但是,在我看來這只是一個創可貼。您應該考慮更高效地存儲粒子,即Quadtree

此外,而不是計算每個距離的開方,你方對比較的距離:

distTo = (xDist * xDist) + (yDist * yDist); 
... 

if(distanceBetween(particleList[i].position, particleList[j].position) < reactDistance * reactDistance) 

你甚至可以預先計算的循環,因此,您沒有那個開銷每次。

+0

謝謝。像Mike B也建議的那樣,改變爲j = i,現在允許多達700個具有平滑幀頻的粒子。 – ShadowByte

+0

如果這只是一個bandaid,我會研究Quadtrees。非常感謝。 – ShadowByte

+0

YouTube上沒有令人滿意的Quadtree教程。 我明白了,它非常有效,但沒有人會解釋如何編寫它,讓我開始接近它。 經過多次優化嘗試之後,我的程序支持大約850個50 FPS的粒子,這很舒服。 – ShadowByte