球与球碰撞优化

时间:2013-08-30 13:30:51

标签: actionscript-3 collision-detection

我正在研究一个球碰撞的项目,我发现这种碰撞的方式很简单。它从数组中获取一个对象,然后将自身与数组中的所有对象进行比较。如何检测碰撞是通过检查中心点距离是否低于两个半径。

这很好用但是当你同时拥有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 );
                }
            }
        }

2 个答案:

答案 0 :(得分:1)

以下是您可以采取的一些措施来加速循环 - 这不是一个明确的列表,但它有助于获得一些额外的性能。

  1. 您正在为支票创建大量临时Point个对象。只需在函数开头创建2个Point对象,并不断更新其xy坐标。这样您就可以避免构建大量对象的成本。内存分配很昂贵,然后垃圾收集器也必须处理它们。
  2. 您应该将mcBall1._radius缓存在局部变量中(例如radius1 - 它比在嵌套循环的每次迭代中读取属性更快。
  3. 不使用distance,而是使用距离的平方 - 这样就可以避免计算平方根。在这种情况下,您可以缓存radius1*radius1
  4. 除了这些之外,您还可以将世界划分为多个部分,并为每个部分分配一个分区索引。为每个球添加一个分区变量 - 当它们移动到世界各地时,您将更新此分区变量。这不是一个昂贵的操作,因为它只是一个简单的检查,看看球是否在哪个分区矩形 - 根据球的速度,它们只能移动到给定分区的许多其他分区。

    如果您使用5x5分区,可以为您提供25个分区,并且您可以随时知道单个分区中有多少个球。在碰撞检测方面,您可以避免检查不在当前分区或任何外围分区中的任何对象。这将为您的碰撞检测代码提供显着的提升。

    查看此问题的示例:Optimizing collison detection code in AS3

    编辑:在我打字的时候,@ Paddyd发布了他对四树的回答 - 这实际上是一个“四叉树”的简单实现,但是没有嵌套分区和5x5而不是2x2分区。 / p>

答案 1 :(得分:1)

阅读Quadtrees

Here是实施一个的例子。