重力游戏如何处理玩家,怪物,物体和地板等移动物体之间的关系?玩家是否经常"落入"地板并被反弹回来?
我发现的两种对碰撞作出反应的方法是将玩家移回到碰撞前的前一个位置,并在移动之前测试新位置以查看是否会导致碰撞,但我看不出这些中的任何一种可以处理一个向上升起并且需要能够提升玩家的平台.我从2D游戏设计的角度来看这个,但我想3D游戏设计中也会出现同样的问题.任何提示?我应该查看的任何参考文献?谢谢.
您可能需要查看GameDev.net的Gravity FAQs以获取一些基本信息.
因为你正在制作一个游戏,而不是一个高度准确的物理建模器,而不是我们可以通过进行Euler集成.如果您对精度的需求增加,我看到的最常用的集成方法是Runge-Kutta(RK4)集成.你很可能不需要这些用于简单的游戏,但它们肯定用于更高级的物理模拟和3D游戏.使用RK4的缺点是复杂性稍微增加并且稍微慢一些.虽然这是非常准确的,但是现在,让我们坚持使用好的欧拉.
我问了一个类似的问题," 如何将重力应用到我的弹跳球游戏中 ",并得到了几个好的答案.你要做的第一件事就是为游戏选择一个任意的重力常数.在我的弹跳球应用中,我使用的默认重力常数为2000px/s.你会想要使用这个重力常数来为你的特定游戏获得所需的效果.
接下来,您要确保自己渲染游戏并独立更新游戏对象.这是为了防止游戏中的对象在快速计算机上快速移动,在慢速计算机上移动速度慢.您希望对象移动的物理和速度与计算机速度无关.关于这个的好文章是游戏物理:修复你的时间步!.
那我们该怎么做呢?您可以跟踪自上次调用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值最终使您的gameObject的速度为零.然后,在作为修剪过程的一部分的碰撞检测过程中,您通常可以跳过检查非移动物体是否与任何物体碰撞(尽管反之亦然!).
我喜欢碰撞的是,一旦我发现物体相互碰撞(相互穿透),我会将它们分开,将它们分开的最小平移距离(MTD).这个步骤是关键,否则你会在游戏中经常看到的错误"卡住"在一起抖动.一旦它们分开,我就计算出我的碰撞响应.
使用此方法,它将在您描述的上升平台的场景中正常工作.平台将继续上升,gameObject将使用自身与平台之间的MTD将自己分开,并且它自然会随之升起.
如果您需要有关碰撞响应的帮助,我建议您查看:
球对球碰撞检测和处理(包括来源)
没有trigonometry.pdf的2D碰撞
添加碰撞检测
GameDev.net论坛!