2016-01-13 124 views
0

我有一系列實體(Manager.Scene.Entities),技術上是圈子。
和我有一個方法,返回實體數組與當前實體相交:快速檢查實體是否相交?

var Intersected = Manager.Scene.Entities.filter(function (another) { 
     //check cases that not initiate intersection to prevent extra calculations 
     if (self.radius < another.radius 
      || another.id == self.id 
      || self.className == another.className) 
      return false; 

     //check circles intersections 
     var dx = self.x - another.x; 
     var dy = self.y - another.y; 
     dx = dx * dx + dy * dy; 
     dy = self.radius + another.radius; 

     return dx < dy * dy; 
    }); 

我型材,並注意到,該方法需要的執行時間,28%(看照片)。

Profile results
是否有可能以某種方式進行優化?


PS。我修改了交點檢查,現在它找到了附近的實體,並且檢查了交點。它需要ex的21%。時間,而不是28%。

var Nearest = Manager.Scene.Entities.filter(function (another) { 
     return self.x * 2 > another.x || self.x/2 < another.x || self.y * 2 > another.y || self.y/2 < another.y; 
    }); 

    var Intersected = Nearest.filter(function (another) { 
     if (self.radius < another.radius || another.id == self.id || self.className == another.className) 
      return false; 

     var dx = self.x - another.x; 
     var dy = self.y - another.y; 
     dx = dx * dx + dy * dy; 
     dy = self.radius + another.radius; 

     return dx < dy * dy; 
    }); 
+1

我假定你計算所有實體交叉:使用[空間劃分策略(https://en.wikipedia.org/wiki/Space_partitioning),以避免'爲O(n^2)'行爲 – BeyelerStudios

+0

@ BeyelerStudios有趣的聽到。我既不做gamedev也不做圖形/物理學,我推斷複雜形狀更有益。 – zerkms

+0

@zerkms比*(邊界球)(https://en.wikipedia.org/wiki/Bounding_sphere)計算*某些東西的邊界框(最小值,最大值)更便宜,但邊界的相交測試球體只是距離的比較,而邊界框涉及多重比較 – BeyelerStudios

回答

0

通過預先計算可能相交的夫婦,您只需花費很少的努力就可以贏得大量時間。每次添加/刪除實體時,都要保持這樣的數組是最新的,並且您可以避免第一次測試。
提供您的身份證是在行動上一個id,代碼可能看起來像:

var colliders []; 
var possibleCollisions = []; 

function addCollider(newCollider) { 
    if (colliders.indexOf(newCollider)>=0) throw('collider already added'); 
    colliders.forEach(function(c) { 
     if ((c.radius>newCollider.radius) && (c.class!=newCollider.class)) 
      possibleCollision.push([ c, 
            newCollider, 
          Math.pow(c.radius + newCollider.radius,2) ]); 
    }); 
    colliders.push(newCollider); 
} 

function removeColliders(deadCollider) { 
    var deadColliderIndex = colliders.indexOf(deadCollider); 
    if (deadColliderIndex==-1) throw('collider already removed'); 
    possibleCollision = possibleCollision.filter(
     function(pc) { return ((pc[0]!=deadCollider)&&(pc[1]!=deadCollider)); 
    }); 
    colliders.splice(deadColliderIndex, 1); 
} 

我們測試的所有碰撞,迭代裏面possibleCollisions。

請注意,您可以存儲半徑(或其平方)的總和以進一步優化事物。

function detectCollision(possibleCollision) { 
    var a = possibleCollision[0], b = possibleCollision[1], 
      radiusSumSq = possibleCollision[3]; 
    var dx = a.x - b.x; 
    var dy = a.y - b.y; 
    return dx*dx + dy*dy <= radiusSumSq; 
} 
+0

如果我理解你是正確的,每當實體添加,刪除或實體的位置改變時,我必須更新碰撞器數據? –

+0

添加/刪除時,是的,你應該更新碰撞列表和可能的碰撞列表,但是當它們移動時不能更新 - 這不會改變碰撞的可能性。 – GameAlchemist