关于碰撞检测对象与移动场景的意见

时间:2010-03-27 15:24:21

标签: language-agnostic collision-detection

所以我的问题很简单,我想这可以归结为你想要如何进行碰撞检测。为了简单起见,我们假设我们正在谈论由边界框定义的2D精灵。另外,让我们假设我的精灵对象具有检测这样的碰撞的功能:S.collidesWith(other);最后场景正在移动,场景中的“墙”可以移动,物体可能不会碰到墙壁。

所以一个简单的实现可能看起来像这样(伪代码):

moveWalls();
moveSprite();
foreach(wall as w) {
    if(s.collidesWith(w)) { 
        gameover();
    }
}

这个问题是如果精灵和墙壁相互移动,视情况而定(例如对角矩)。他们可能会相互通过(不太可能,但可能发生)。

所以我可以这样做。

moveWalls();
foreach(wall as w) {
    if(s.collidesWith(w)) { 
        gameover();
    }
}
moveSprite();
foreach(wall as w) {
    if(s.collidesWith(w)) { 
        gameover();
    }
}

这会照顾彼此的问题,但另一个罕见的问题出现了。如果它们彼此相邻(字面意思是下一个像素)并且墙和精灵都向左移动,那么我将得到无效的碰撞,因为墙移动,检查碰撞(命中)然后精灵被移动了。这似乎不公平。此外,冗余碰撞检测感觉效率非常低。我可以给予玩家移动优先级以缓解第一个问题,但它仍然会检查两次。

moveSprite();
foreach(wall as w) {
    if(s.collidesWith(w)) { 
        gameover();
    }
}
moveWalls();
foreach(wall as w) {
    if(s.collidesWith(w)) { 
        gameover();
    }
}

我只是过度思考这个问题,如果这只是被描述为“它会发生得非常罕见,没有人会关心”?当然,看看基于精灵的旧游戏,我经常会发现碰撞检测存在细微缺陷的情况,但我认为现在我们可以做得更好:-P。人们的想法是什么?

2 个答案:

答案 0 :(得分:2)

是否值得提高准确度是我们无法告诉您的,但在游戏测试期间应该变得明显。至于提高碰撞检测的可靠性,您有以下几种选择:

  1. 减小模拟步长。如果步长*(玩家最大速度+墙壁最大速度)< (玩家宽度+墙宽),你不会错过任何碰撞。
  2. 同时检查播放器在模拟步骤之前和之后是否与墙的同一侧。
  3. 不是仅在每个模拟步骤结束时检查碰撞,而是导出一个公式,计算墙和玩家在当前速度下碰撞的时间,如果该时间在当前模拟中,则标记碰撞步。这可能在你的情况下有点过分,但可以用来模拟诸如弹跳墙之类的东西。

答案 1 :(得分:0)

这很大程度上取决于您用来检查碰撞的频率(以及玩家的输入设备)。当您经常检查时,两个“同时”移动的情况将变得不太可能。如果它是一个基于回合的策略游戏,那将是一个不同的问题。

那就是说,我不知道,你正在详细使用哪种型号,但是如果你有一个线程,它检查玩家输入,一个进行运动计算和碰撞检测,那么两者都必须是无论如何,同步(读/写锁)。在那种情况下,很清楚,首先发生了什么。同样的,如果你只使用一个线程。

根据物理模型,输入可以控制加速度,这将决定速度,而速度又决定了位置。如果物体从前一个位置移动到(可能的)下一个位置的线在那时穿过墙的位置,则会发生碰撞(考虑到可能发生碰撞的整个轮廓)。

可能更难的事情是计算反弹的效果。当我写一个基于OpenGL的游戏时,我发现这是真的,墙壁不能移动,但地板可以倾斜:当弹跳不足以抵抗墙壁的加速度时,你仍然会碰撞后在墙内。在投入一些努力后,我认为,它的效果非常好(包括沿着墙壁滚动,这是另一个问题),但是在移动墙壁的情况下,它甚至会更加困难。