我有一些实体(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%的执行时间(见图片)。
有可能以某种方式优化它吗?
<小时/> PS。我修改了交叉点检查,现在它找到了附近的实体,而不是检查交叉点。它占前者的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;
});
答案 0 :(得分:0)
通过预先计算可能相交的情侣,您可以通过一些努力赢得大量时间。每次添加/删除实体时都要保持这样的阵列最新,并且可以避免第一次测试 如果你的id是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;
}