代码之家  ›  专栏  ›  技术社区  ›  Evan Teran

对运动场景中物体碰撞检测的几点看法

  •  2
  • Evan Teran  · 技术社区  · 16 年前

    所以我的问题很简单,我想它可以归结为你对碰撞检测的兴趣。为了简单起见,假设我们讨论的是由边界框定义的二维精灵。另外,假设我的精灵对象有一个检测碰撞的函数,如下所示: S.collidesWith(other);

    因此,一个简单的实现可能如下所示(psuedo代码):

    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();
        }
    }
    

    我是不是只是对这个问题考虑得太多了,是否应该把这个问题归结为“它的发生非常罕见,没有人会在意”?当然,在旧的基于sprite的游戏中,我经常会发现碰撞检测有细微的缺陷,但我认为现在我们可以做得更好。人们的想法是什么?

    2 回复  |  直到 16 年前
        1
  •  2
  •   meriton    16 年前

    我们不能告诉你是否值得提高准确度,但应该在测试过程中变得明显。为了提高碰撞检测的可靠性,您有几种选择:

    1. 减小模拟步长。如果步长*(玩家最大速度+墙最大速度)<(玩家宽度+墙壁宽度),你不会错过任何碰撞。
    2. 不是只在每个模拟步骤结束时检查碰撞,而是导出一个公式,根据墙和播放器的当前速度计算碰撞的时间,如果该时间在当前模拟步骤内,则标记碰撞。在您的案例中,这可能是过度的,但在建模诸如从墙上反弹之类的东西时可能很有用。
        2
  •  0
  •   Chris Lercher    16 年前

    这在很大程度上取决于检查碰撞的频率(以及播放器的输入设备)。当你经常检查的情况下,两个移动'在同一时间'将变得不太可能。如果这是一个基于回合的策略游戏,这将是一个不同的问题。

    也就是说,我不知道你在详细使用哪个模型,但是如果你有一个线程,检查播放器输入,还有一个线程进行运动计算和碰撞检测,那么两者都必须同步(读/写锁)。在这种情况下,很明显,先发生了什么。同样的道理,如果你只使用一个线程。

    根据物理模型,输入可以控制加速度,从而决定速度,进而决定位置。如果对象从上一个位置到(可能的)下一个位置的移动线与当时墙的位置相交,则会发生碰撞(考虑到可能发生碰撞的整个轮廓)。

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

    推荐文章