我正在研究一个球碰撞的项目,我发现这种碰撞的方式很简单。它从数组中获取一个对象,然后将自身与数组中的所有对象进行比较。如何检测碰撞是通过检查中心点距离是否低于两个半径。
这很好用但是当你同时拥有100多个对象时,会有很多冗余。这意味着为什么单个对象会检查屏幕另一侧的对象位置,它碰撞的可能性很低。
我发现了一个理论,一个对象应该只检查比自身大的区域中的其他对象。然后,如果该区域中有另一个对象,则会开始检测碰撞。但这只会创建额外的检查,因为对象必须检查所有对象(如果它在区域中),然后检查对象是否发生碰撞。
有没有一种有效检测碰撞的方法?
public function newHandler():void
{
for ( var i:int = 0; i < _objectArrayLayer1.length; i++ )
{
mcBall1 = _objectArrayLayer1[i];
for ( var j:int = i + 1; j < _objectArrayLayer1.length; j++)
{
mcBall2 = _objectArrayLayer1[j];
p1 = new Point(mcBall1.nX, mcBall1.nY);
p2 = new Point(mcBall2.nX, mcBall2.nY);
distance = Point.distance(p1,p2);
radius1 = mcBall1._radius ;
radius2 = mcBall2._radius ;
if (distance <= radius1 + radius2)
{
solveBalls( mcBall1, mcBall2 );
}
}
}
答案 0 :(得分:1)
以下是您可以采取的一些措施来加速循环 - 这不是一个明确的列表,但它有助于获得一些额外的性能。
Point
个对象。只需在函数开头创建2个Point
对象,并不断更新其x
和y
坐标。这样您就可以避免构建大量对象的成本。内存分配很昂贵,然后垃圾收集器也必须处理它们。mcBall1._radius
缓存在局部变量中(例如radius1
- 它比在嵌套循环的每次迭代中读取属性更快。distance
,而是使用距离的平方 - 这样就可以避免计算平方根。在这种情况下,您可以缓存radius1*radius1
。除了这些之外,您还可以将世界划分为多个部分,并为每个部分分配一个分区索引。为每个球添加一个分区变量 - 当它们移动到世界各地时,您将更新此分区变量。这不是一个昂贵的操作,因为它只是一个简单的检查,看看球是否在哪个分区矩形 - 根据球的速度,它们只能移动到给定分区的许多其他分区。
如果您使用5x5分区,可以为您提供25个分区,并且您可以随时知道单个分区中有多少个球。在碰撞检测方面,您可以避免检查不在当前分区或任何外围分区中的任何对象。这将为您的碰撞检测代码提供显着的提升。
查看此问题的示例:Optimizing collison detection code in AS3
编辑:在我打字的时候,@ Paddyd发布了他对四树的回答 - 这实际上是一个“四叉树”的简单实现,但是没有嵌套分区和5x5而不是2x2分区。 / p>
答案 1 :(得分:1)