处理碰撞 - 阵列看起来昂贵

时间:2012-03-12 17:01:01

标签: java android collision-detection

我的android程序中有一个碰撞检测方法来检测两个球碰撞的时间并计算它们的新速度。每个球都存储在一个数组Ball[] ballArray中。为了处理碰撞,我遍历每个球,取其中心坐标并计算周围区域。如果任何其他球的中心位于该区域内,那么我检查两个球是否发生碰撞。

我的方法基本如下

public void handleCollisions(){
    int size = ballArray.length;

    for(int i = 0; i < size; i++){
         Ball ball = ballArray[i];
         int centerX = ball.centerX;
         int centerY = ball.centerY;
         int radius = ball.radius;

         //calculate box around ball
         int lowXLimit =  (centerX - radius - largestPossibleRadius);
         int highXLimit =  (centerX + radius + largestPossibleRadius);
         int lowYLimit =  (centerY- radius - largestPossibleRadius);
         int highYLimit =  (centerY+ radius + largestPossibleRadius);

        for(int j = j+1; j < size; j++){
            Ball ball2 = ballArray[j];
            int centerX2 = ball.centerX;
            int centerY2 = ball.centerY;
            int radius2 = ball.radius;

            //if ball2 is inside the possible collision region around ball1
            if (centerX2  > lowXLimit && centerX2 < highXLimit  && centerY2 > lowYLimit && centerY2 < highYLimit) {
                //do calculations to determine new velocities
            } 
}

我的代码性能很差,并运行了一个跟踪视图。令我惊讶的是,此方法中只有大约5%的执行时间用于进行冲突解决计算(相当多的浮点除法,乘法)。事实上,这种方法中大约60-70%的时间只是从球阵列中访问球(线Ball ball = ballArray[i]Ball ball2 = ballArray[j])。

我尝试使用ArrayList,但情况更糟。我有什么办法可以加快这段代码的速度吗?或许另一种数据结构?这对我来说似乎很长一段时间。我应该尝试减少Ball中的成员变量数量吗?

5 个答案:

答案 0 :(得分:2)

尝试按位置排序球。这可能会减少你需要做的计算次数,因为你只需要将每个球与附近的其他球进行比较 - 一旦球太远(在你排序的轴上,至少)那么你不需要考虑更远的球。

答案 1 :(得分:1)

短暂的一点: - 在你的第二个循环中你可以从i + 1开始(我相信这是你的意图)

for(int j = i+1; j < size; j++){

如果您真的在搜索数据结构,那么您可以查看空间分区树。 (例如kd-treesQuad-trees等。从您的代码我假设一个2D空间)。但是,您应该意识到在动态环境(移动球)中维护此类数据结构可能过于昂贵。您应该决定能为您带来最佳回报的详细程度。

答案 2 :(得分:0)

有些要点可以优化:

你可以用半径来计算球碰撞。球之间的距离= sqrt((x1-x2)^ 2 +(y1-y2)^ 2),现在如果球之间的距离<1。 (radius1 + radius2)然后它们发生碰撞。

要有效地计算,你应该保持距离平方(没有sqrt)并与(radius1 + radius2)^ 2进行比较。这种方式可能比你现在的做得快。

如果你有n个球你当前必须做n ^ 2比较,这对很多球来说相当多。因此,寻找优化是一个很好的观点:

有一些非常先进的“空间数据结构”(谷歌那样)可以让你比较球的数量少于所有的球(只是球足够接近所以它们很可能碰撞)。这些问题是你必须保持这种结构(每当你的球移动时更新它),这通常是相当多的计算,并可能最终慢慢你的方法。

示例:http://www.gamerendering.com/2008/11/17/uniform-grid/ 你使用一个网格,其中cellize =一个球可以拥有的最大直径。每当你移动一个球时,你就会更新它在网格中的位置(这是一个非常简单的除以网格宽度)。然后你只需要比较这个或直接相邻的细胞内的球和球。

  

我尝试过使用ArrayList,但情况更糟。我有什么办法可以加快这段代码的速度吗?或许另一种数据结构?这对我来说似乎很长一段时间。我应该尝试减少Ball中的成员变量数吗?

使用不同的类/成员几乎无法做任何事情。你的Ball []数组与公共成员是最有效的方法。 Ball的成员数量应该对速度没有影响。

答案 3 :(得分:0)

您多久调用一次handleCollisions()?这些球移动的速度有多快?

我的猜测是你必须在这两个数字之间做出更好的匹配,并与距离进行比赛。

例如,如果1球是距离最近的球20个单位并且自上次调用handleCollisions()以来所有球都移动了2个单位,那么这个球不可能发生碰撞,所以跳过它。在某些情况下,也许您可​​以跳过所有球(跳过调用handleCollisions)。

答案 4 :(得分:0)

您是否还考虑过不打算将当前球分配给变量? 你看到花在“访问数组”上的时间实际上可能是花在分配和分配局部变量上。您可以通过索引到阵列中来简单地访问球。我不确定会有多大差别,但值得一试。

相关问题