避免基于网格的碰撞检测中的重复?

时间:2012-11-08 17:55:58

标签: java algorithm

这是我的问题。

我的游戏,有效渲染和碰撞分为区域。每个区域中将有许多将动态移动的对象。当它们移动时,我会确定它们所在的区域。

这意味着和对象可以在多个区域。

如果我知道对象A在区域1和2中,对象B也在1和2中,那么会发生什么:

for each object in region 1 and 2
if A collides with B...

我实际上会两次检查同一对。

如果只检查一次,我该怎么办?是否有我应该使用的数据结构或算法?

4 个答案:

答案 0 :(得分:1)

如果您可以对对象强制执行排序,那么您只需要按顺序检查a < b对的对。可以是任何东西:数组中的索引,指针(对于允许指针值访问的语言,可以是yay)。

for(Object a : list) {
    for(Object b : list) {
        if (a.compare(b) < 0) {

非常简单,实际上会解决问题。

如果您有整数索引存储空间,则可以执行

for(int i = 0; i < list.length; i++) {
    for(int j = i + 1; j < list.length; j++) {

你不会得到重复的。这适用于ArrayList,但可能不适用于任意类型。您可能能够克隆一些迭代器,但我不会打赌......

for(Iterator<Object> iter = list.iterator(); iter.hasNext(); ) {
    Object a = iter.next();
    Iterator<Object> iter2 = iter.clone();
    for(;iter2.hasNext();) {
        Object b = iter.next();

但严重的是,这是一个黑客攻击。如果它适用于所有的Java集合,我会感到惊讶。使用Java迭代器的更可靠但同样的hackish变通方法:

for(Object a : list) {
    Iterator<Object> biter = list.iter();
    while(biter.next() != a) { };
    for(; biter.hasNext(); ) {
        Object b = biter.next();

一般来说,java foreach语法for(Clazz object : iterable) {是“可爱的”,但Iterator强大得多。事实上,上面循环的旧整数也像魅力一样。

答案 1 :(得分:0)

为什么不存储先前计算的结果?

实际上,它会变成:

for each object in region 1 and 2
    if results doesn't contain (A collides with B)
       ...
       results = result of (A collides with B)

答案 2 :(得分:0)

没有。可能是你的网格太小了。边界框也不是很好的碰撞检测,你可以避免空白区域的插入和删除。

答案 3 :(得分:0)

您可以使用四叉树(http://en.wikipedia.org/wiki/Quadtree)代替常规间隔网格,这样可以更好地索引不同大小的对象。您可以让四叉树确定合适的单元格大小,而不是必须选择单个单元格大小(对于某些对象可能太大而对于其他对象而言太小)。

然而,即便如此,你也无法阻止单个对象在多个树节点中出现,但这不应该是你应该尝试实现的目标 - 你唯一应该防止的是每个对象都出现在数十个或数百个单元格或四叉树节点,因为 会影响性能。

因此,如果所有对象的大小大致相同,只要单元格与对象一样大(或者可能大两倍?),常规网格可能仍然是最佳选择。