【问题标题】:Checking Collisions In 2D Platformer With Tiles使用瓷砖检查 2D 平台游戏中的碰撞
【发布时间】:2012-01-11 19:20:59
【问题描述】:

我和我的团队正在使用 C++/SDL/OpenGL 开发一个 2D 平台游戏,我们已经定义了一个碰撞系统,但是我们在检查与 tilemap 的碰撞时遇到了问题。

tilemap 的瓦片是 32x32,所以我们尝试定义玩家在 X 和 Y 方向的最大速度小于 32,因为在这种情况下,我们发现如果速度大于瓦片大小,在检查碰撞时,位置会以超过 32 的速度更新,所以在这种情况下,位置会跳过一个瓷砖,这会导致验证的巨大问题,所以目前我们将 X 和 Y 速度限制为 30,但是我们不知道如何使速度大于图块大小而不会丢失完整的碰撞检测以及一些可能被跳过的图块。

【问题讨论】:

    标签: c++ 2d collision


    【解决方案1】:

    Sweep tests.

    基本上,您需要检查静止关卡几何框与将移动框从(位置)移动到(位置+速度)形成的形状之间的碰撞,而不是简单的框/框碰撞。

    【讨论】:

    • 那么,你说不是在检查之前移动框,而是在碰撞检查期间仅在检查碰撞结果为假时更新位置?
    • 如果你的盒子/扫描盒子检查是假的,你很高兴,只需将你的盒子移动到它想去的地方。如果这是真的,您需要弄清楚在dt 期间它何时变为真的。我建议使用二分搜索,沿 (position+velocityalpha) 改变扫描框的第二个点,其中 alpha 在 0.0 和 1.0 之间变化。当您发现碰撞发生的时间时,您只需将框的最终位置设置为(位置+速度alpha)。
    • 非常感谢您的回答。我已经应用了这种方法并且效果非常好。
    【解决方案2】:

    您如何定义速度?让我们假设它是每秒像素,然后为了允许更高的速度,您应该在一秒钟内多次检查碰撞。所以在伪代码中:

    double time = GetElapsedTime();
    player.updatePosition(speed * time);
    

    现在它可能比那更复杂,但你明白了;要么做这样的事情,要么使用精确的碰撞检测(我曾经找到一篇很棒的文章,但似乎找不到它),它使用方程式来“预测”物体何时何地发生碰撞。

    【讨论】:

      【解决方案3】:

      我用过的一种方法:

      当移动一个(玩家、其他精灵……)时,将它通过的所有图块确定为一个矩形。

      举例:

      on tick:
         player-box = (player.x, player.y) - (player.x + player.width, player.y + player.height)
         player-delta.x = (player-speed.x × (now - last-updated))
         player-delta.y = (player-speed.y × (now - last-updated))
         player-end-box = player-box + player-delta
           { i.e. player-end-box = ( player-box.top-left.x + player-delta.x,
                                     player-box.top-left.y + player-delta.y ) -
                                   ( player-box.bottom-right.x + player-delta.x,
                                     player-box.bottom-right.y + player-delta.y ) }
         player-collided = ( min (player-box.top-left.x, player-end-box.top-left.x),
                             min (player-box.top-left.y, player-end-box.top-left.y) ) -
                           ( max (player-box.bottom-right.x, player-end-box.bottom-right.x),
                             max (player-box.bottom-right.y, player-end-box.bottom-right.y) )
      

      然后您可以使用player-collided 的每个角的modulo 32 来确定玩家(或任何精灵)已经(试图)遮挡的图块。

      通常,您可能希望在播放器的实际尺寸上放置一个小的“边距”,以避免 1px 或 2px 重叠......(即,将起始框设置为比实际精灵小几个 px),具体取决于如何准确的玩家控制,以及精灵和一个瓷砖之间的大小差异。

      请注意,非常快的(每次更新许多图块)对角线移动会使此设置无效,但它适用于非常快速的线性(水平或垂直)移动。如果您在对角线上移动“太快”,对于这种方法,请考虑将开始和结束矩形连接成一个多边形(不规则六边形)并测试每个图块是否包含该六边形的任何部分。

        for each tile in (big rectangular area):
            if tile is inside polygon (hexagon of movement):
                add tile to list of collisions
      

      这本质上是对常见 2D 情况的完整边界几何检查的优化。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-01-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-08-20
        • 2011-07-06
        • 2012-06-02
        相关资源
        最近更新 更多