0

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

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

2 回答 2

1

这里有一些你可以做的事情来加速你的循环——这不是一个确定的列表,但它会帮助你获得一些额外的性能。

  1. 您正在为您的支票创建大量临时Point对象。只需Point在函数开头创建 2 个对象并不断更新它们的x坐标y。这样您就可以避免构建大量对象的成本。内存分配很昂贵,然后垃圾收集器也必须处理它们。
  2. 您应该缓存mcBall1._radius在局部变量中(例如radius1- 它比在嵌套循环的每次迭代中读取属性更快。
  3. 不要使用distance,而是使用距离的平方 - 这样可以避免计算平方根。在这种情况下,您可以缓存radius1*radius1.

除了这些,您还可以将您的世界划分为多个部分,并为每个部分分配一个分区索引。为每个球添加一个分区变量 - 当它们在世界各地移动时,您将更新此分区变量。这不是一个昂贵的操作,因为它只是一个简单的检查,看看球是否在哪个分区矩形内 - 根据球的速度,它们只能从给定的分区移动到这么多的其他分区。

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

看这个问题的例子:Optimizing collison detection code in AS3

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

于 2013-08-30T13:39:29.830 回答
1

阅读四叉树

是一个实现的示例。

于 2013-08-30T13:39:45.653 回答