重力游戏如何处理玩家,怪物或物体等移动物体与地板之间的关系?玩家是否经常“落入”地板并被反弹回来?
我发现的两种对碰撞作出反应的方法是在碰撞前将玩家移回原先的位置,并在移动之前测试新位置以查看是否会导致碰撞,但我不知道如何其中任何一个都可以处理一个向上升起并需要能够提升玩家的平台。我从2D游戏设计的角度来看这个,但我想3D游戏设计中也会出现同样的问题。任何提示?我应该查看的任何参考文献?感谢。
答案 0 :(得分:15)
您可能需要查看GameDev.net's Gravity FAQs以获取一些基本信息。
因为你正在制作一个游戏,而不是一个高度准确的物理建模师,而不是我们可以通过Euler integrations逃脱。如果您对准确性的需求增加,我看到的最常用的集成方法是Runge-Kutta (RK4) integration。你很可能不需要这些用于简单的游戏,但它们肯定用于更高级的物理模拟和3D游戏。使用RK4的缺点是复杂性稍微增加并且稍微慢一些。虽然这是非常准确的,但是现在,让我们坚持使用好的欧拉。
我问了一个类似的问题,“How do I apply gravity to my bouncing ball game”,并得到了几个很好的答案。你要做的第一件事是为你的游戏选择一个任意的重力常数。在我的弹跳球应用中,我使用的默认重力常数为2000px / s。你会想要使用这个重力常数来为你的特定游戏获得所需的效果。
接下来,您要确保自己渲染游戏并独立更新游戏对象。这是为了防止游戏中的对象在快速计算机上快速移动,在慢速计算机上移动速度慢。您希望对象移动的物理和速度与计算机速度无关。关于此的一篇好文章是Game Physics: Fix your timestep!。
那我们该怎么做?您可以跟踪自上次调用Update方法以来经过的时间。我创建了2个线程,虽然它不是直接需要的。我有一个游戏更新线程和一个渲染线程。更新线程控制更新游戏对象位置。更新线程知道它之前被调用的时间,当前时间和从中计算自调用更新方法以来经过的时间。
要应用重力,我们只需通过我们的重力常数乘以经过的时间来增加物体的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最终使您的gameObject的速度为零。然后,在作为修剪过程的一部分的碰撞检测过程中,您通常可以跳过检查非移动物体是否与任何物体碰撞(尽管反之亦然!)。
我喜欢碰撞的事情是,一旦我发现物体碰撞(相互穿透),我会将它们分开,将它们分开的最小平移距离(MTD)。这个步骤是关键,否则你会在游戏中经常看到的错误“卡住”在一起抖动。一旦它们分开,我就计算出碰撞响应。
使用此方法,它将在您描述的上升平台的场景中正常工作。平台将继续上升,gameObject将使用自身与平台之间的MTD将自己分开,它自然会随之升起。
如果您需要有关碰撞响应的帮助,我建议您查看:
答案 1 :(得分:2)
在某些游戏中使用的一种方法是作弊:拥有一个单独的行走状态而不是空中状态。在行走时,游戏引擎可以确定被掠过的表面的坡度,如果不是太陡,则可以在表面方向上移动角色,并为角色提供相对于表面的正确垂直位置。
至于物理学,我正在成为Gamasutra: Advanced Character Physics中描述的verlet集成的粉丝。它简化了物理更新方程式(不必跟踪速度!),它简化了碰撞(不必调整速度!)。也就是说,如果您需要准确性,它确实有a few nuances。
答案 2 :(得分:1)
关于这个主题的最完整的教科书之一是Realtime Collision Detection by Christer Ericson。他也有a companion blog。 Eric Lengyel的Mathematics for 3D Game Programming and Computer Graphics也很有用。
答案 3 :(得分:1)
我不是一名游戏程序员,但这是我的理解:
答案 4 :(得分:1)
除了建模碰撞之外,一个好的方法是模拟持续的能量转移(或动量,或仅仅是速度,取决于模拟的复杂性)。当您的播放器站在平台上时,将该信息存储在代表平台的对象中,并且无论何时调整对象的速度,您都可以直接将该更改应用于如此链接的播放器或其他对象。