高效的碰撞调整

时间:2014-01-03 17:17:53

标签: java android collision-detection android-canvas

我在Android上编写了一个增强现实框架。该框架的一个特点是建立在碰撞检测和调整中;意思是,如果检测到检测,框架将移动对象,使它们不再发生碰撞。它按预期工作,但我想知道是否有更有效的方法来处理它。或者,如果行业中有一般方法来处理这些情况。

代码在Android View对象的onDraw()中调用,该对象经常被调用。

这是碰撞检测和调整代码:

private static final Set<Marker> updated = new HashSet<Marker>();
private static final int COLLISION_ADJUSTMENT = 100;

private static void adjustForCollisions(Canvas canvas, List<Marker> collection) {
    updated.clear();

    // Update the AR markers for collisions
    for (Marker marker1 : collection) {
        // If marker1 has already been updated or is not in view then skip it
        if (updated.contains(marker1) || !marker1.isInView())
            continue;

        int collisions = 1;
        for (Marker marker2 : collection) {
            // If marker2 has already been updated or is not in view or is the same as marker 1 then skip it
            if (updated.contains(marker2) || !marker2.isInView() || marker1.equals(marker2))
                continue;

            // Detect a collision
            if (marker1.isMarkerOnMarker(marker2)) {
                // Move the marker "up" the screen by COLLISION_ADJUSTMENT pixels
                marker2.getLocation().get(locationArray);
                float y = locationArray[1];
                float h = collisions * COLLISION_ADJUSTMENT;
                locationArray[1] = y + h;
                marker2.getLocation().set(locationArray);
                marker2.update(canvas, 0, 0);
                collisions++;
                // mark marker2 as updated
                updated.add(marker2);
            }
        }
        // mark marker2 as updated
        updated.add(marker1);
    }
}
github上的

Android AR Framework

1 个答案:

答案 0 :(得分:0)

一种简单的改进方法是不使用for(Object o : collection)如果您有很多对象,这会对性能产生巨大影响。

for(int i = 0; i < collection.length();i++){

    for(int j = i+1; j < collection.length(); j++){
         //check collision collection[i] vs collection[j]
    }
}

以上情况更好,因为我们只检查一个对象与集合中的对象,因为之前的迭代已经检查过碰撞。

即在第一次迭代时,你检查第一个对象(一个),所以当它检查对象的时间(两个)时,不需要再检查(一个)。

另外一般来说,你想避免onDraw()中的任何工作,因为你想尽可能快速和平滑地绘制,而不会挂在caluclations上,所以最好把它们移到其他地方。

对于进一步的研究,已经有一些不同的想法可以优化碰撞,例如将空间划分为象限,只检查对象与同一象限中的其他对象。

编辑添加循环步骤

outer i=0
   inner (check [i] vs [j])
        j=1 [0] vs [1]
        j=2 [0] vs [2]
        j=3 [0] vs [3]
        .....
        j=N [0] vs [N] (N is last index) 
    end inner

we've now checked [0] against all other objects and the inner loop finishes
outer loop incrments i

i++
i=1

outer i=1
   inner (check [i] vs [j])
        j=2 [1] vs [2]
        j=2 [1] vs [3]
        j=3 [1] vs [4]
        .....
        j=N [1] vs [N] (N is last index) 
   end inner
....

i++
i=N-1;

outer i=N-1
    inner (check [i] vs [j])
        j=N [N-1] vs [N]
    end inner
end outer

您可以从步骤中看到[i]永远不会对自身或任何先前的索引进行检查,从而大大减少了我们进一步遍历集合所需的检查次数。

[0] vs [1]与[1] vs [0]相同,所以基本上我们只是消除两次检查相同的事情。