代码之家  ›  专栏  ›  技术社区  ›  Andru Luvisi

游戏物体与地面之间的碰撞与重力有关?

  •  12
  • Andru Luvisi  · 技术社区  · 16 年前

    重力游戏是如何处理移动物体(如玩家、怪物或物体)与地面之间的关系的?球员是否经常“跌入”地板并被弹起?

    我发现两种应对碰撞的方法是将玩家移回碰撞前的位置,并在移动前测试新位置,看是否会导致碰撞,但我不知道这两种方法如何处理向上升起的平台,需要能够抬起玩家。我是从2D游戏设计的角度来看这个问题的,但我想同样的问题也会发生在3D游戏设计中。有什么提示吗?有什么我应该查的参考资料吗?谢谢

    5 回复  |  直到 16 年前
        1
  •  18
  •   Community CDub    7 年前

    你可能想退房 GameDev.net's Gravity FAQs

    因为你在做一个游戏,而不是一个高精度的物理建模师,所以我们可以不做 Euler integrations . 如果您需要提高精度,我看到使用的最流行的集成方法是 Runge-Kutta (RK4) integration

    我问了一个类似的问题,” How do I apply gravity to my bouncing ball game ,并得到了几个很好的答案。您要做的第一件事是为您的游戏选择一个任意重力常数。在我的弹跳球应用程序中,我使用默认重力常数2000px/s。您需要使用此重力常数来获得特定游戏所需的效果。

    接下来,要确保渲染游戏并独立更新游戏对象。这是为了防止游戏中的对象在快速计算机上移动过快,在慢速计算机上移动过慢。你希望你的物体移动的物理和速度与计算机的速度无关。这方面的一篇好文章是 Game Physics: Fix your timestep! .

    那我们怎么做呢?跟踪自上次调用Update方法以来经过的时间。我创建了两个线程,尽管它不是直接必需的。我有一个游戏更新线程和一个渲染线程。更新线程控制更新游戏中对象的位置。更新线程知道上次调用它的时间、当前时间,并从中计算自调用更新方法以来经过的时间。

    要应用重力,我们只需将重力常数乘以经过的时间,再加上物体的Y速度。

    private long previousTime = System.currentTimeMillis();
    private long currentTime = previousTime;
    
    public void updateGame()
    {
        currentTime = System.currentTimeMillis();
        float elapsedSeconds = (currentTime - previousTime) / 1000f; 
    
        foreach(GameObject gameObject in gameObjects)
        {
            // Apply gravity to velocity vector
            gameObject.velocity.y += (gravityConstant * elapsedSeconds); 
    
            // Move objects x/y position based off it's velocity vector
            gameObject.position.x += (gameObject.velocity.x * elapsedSeconds); 
            gameObject.position.y += (gameObject.velocity.y * elapsedSeconds);
    
        }
    
        checkCollisions();
    
        previousTime = currentTime;
    }
    

    这将根据其速度向量移动所有对象,并根据重力常数对其应用重力。最棒的是它独立于计算机的速度!

    回答你的另一个问题,是的,物体的y向量上会不断地有重力。所以它会不断地与地板碰撞。但是,您要做的一件事是使用 Epsilon value

    我喜欢对碰撞做的是,一旦我发现物体发生碰撞(相互穿透),我会通过它们的最小平移距离(MTD)将它们分开。这一步很关键,否则你会发现游戏中经常出现的bug,对象“卡”在一起,不停地移动。一旦它们分开,我计算碰撞响应。

    使用此方法,它将在您描述的上升平台场景中正常工作。平台将继续上升,游戏对象将使用MTD在自身和平台之间分离,并自然地随之上升。

        2
  •  2
  •   Paul    16 年前

    至于物理,我正在成为verlet集成的粉丝,如中所述 Gamasutra: Advanced Character Physics . 它简化了物理更新方程(不必跟踪速度!),简化了碰撞(不必调整速度!)。也就是说,它确实有 a few nuances

        3
  •  1
  •   Crashworks    16 年前
        4
  •  1
  •   Neil Coffey    16 年前

    我不是专门的游戏程序员,但我的理解是:

    • 在一个具有“无限帧速率”的理想世界中,你会在碰撞发生的那一刻准确地检测到碰撞,并使用一点标准物理来模拟碰撞后物体的新速度和加速度(参见标准高中力学教科书,或各种题为“游戏程序员物理学”的书籍)
    • 实际上,由于您有固定的帧速率,因此实体仅以一定的粒度移动,因此通常需要添加额外的技巧,例如提前计算实体在下一帧上移动的相对路径,并查看是否有任何路径相交
    • 如果它们相交,那么相交点实际上是一个 ,但有点不准确,物体真正碰撞的点;然后,您可以选择不关心,将该估计值作为交点,线性插值以获得碰撞点处的速度,或者进行更精确的计算,现在您已经发现它们将相交,以获得实际碰撞点/时间/速度
        5
  •  1
  •   Sparr    16 年前

    推荐文章