我在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上的
答案 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]相同,所以基本上我们只是消除两次检查相同的事情。