我正在尝试计划我开始编码的游戏。 (非常开头)
我的问题是我希望所有游戏对象的加速/移动部分基于加速力与阻力(从而导致终端速度作为速度的上限)
虽然我可以走另一条路,但如果可能,我宁愿不去。此外,有人建议(由朋友)我可以使用物理库,但这似乎有点过分,此外,我想自己学习和理解这些概念 - 我总觉得我更好地了解自己的程序做。
我正在进行2D游戏并使用Vector2变量来获得位置,航向和推力(应用的加速力)。它是自上而下的,因此引力不是等式的一部分。
在我编写代码之前,我正在使用Excel编写测试用例 - 这是我在将数学提交给代码之前检查数学的方法。而且我发现我使用拖曳方程正在使问题帧速率依赖!! 具体来说,帧速率越高,得到的终端速度越低。
我一直在尝试根据需要修改方程式以考虑帧速率,但它让我望而却步。
如果您想使用相同的电子表格you can download the spreadsheet here。
但你不必 - 这里有具体细节。
我理解的拖曳方程是:
Drag = 0.5 * FluidDensity * Velocity * Velocity * DragCoefficient * IncidenceArea
使用从稀薄空气中挑选的一些数字进行计算,如果流体密度为0.233且阻力系数为0.4且附带区域为0.1且加速力为每秒50像素,则会发生以下情况:
如果我计算加速度每0.25秒(每四分之一秒一次)以加速力的1/4(以匹配时间)应用,那么我们达到终端速度约为每秒39.3像素。
如果我计算加速度而不是每秒,我们达到终端速度约为每秒53.6像素。
具体来说,每次我计算给定的DeltaTime时,结果的速度计算为(代码来自我的头 - 而不是来自IDE - 如果有错误则道歉):
//In globals / initialization:
Vector2 Position;
Vector2 Speed;
Vector2 ThrustForce;
float Density = 0.233f;
float DragCoefficient = 0.4f;
float IncidentalArea = 0.1f;
//In the update loop
//DeltaTime is a float based upon how much of a second passed
Vector2 AccelerationToApply = ThrustForce * DeltaTime;
Vector2 NewSpeed = Speed + AccelerationToApply;
Vector2 Drag = Speed * Speed * 0.5f * Density * DragCoefficient * IncidentalArea;
NewSpeed -= Drag;
Speed = NewSpeed;
这就是问题数学。这是一个问题:
如何表达它以使其与帧速率无关?
答案 0 :(得分:3)
经典的方法是独立于游戏循环帧速率来模拟模拟物理时间,如果需要,每帧计算多个子迭代以推进物理学。这允许您控制您的时间步长(通常使其小于主帧速率),这也有助于控制其他可能不稳定的计算(例如振荡器)。这当然意味着您的物理需要比实际更快地计算选择固定时间步的时间,否则你的世界将进入慢动作。
说到不稳定性,我想你会在当前的实现中看到一些振荡效应,这取决于你是否在给定的时间步长内超过终端速度。解决此问题的一种方法是通过分析积分计算速度,而不是使用增量步骤进行近似。为此,将您的公式表示为微分方程,看看它是否是一种可以通过分析方法轻松解决的形式。
答案 1 :(得分:1)
上面的代码中缺少两部分。虽然我玩过一部分“开”和“关”来实验确定是否需要,但没有另一部分我找不到合适的答案。
这两个部分是这样的:合成阻力需要乘以时间步长以减少其对加速度的影响,但也可能更重要的是 - 要施加在该框架上的加速力需要阻力在应用于速度之前减去它 - 而不是像我上面那样。
修改后的(现在是帧速率独立的)代码如下所示: 另外,为简单起见,我将4个“常数”系数减少到一个系数。
//In globals / initialization:
Vector2 Position;
Vector2 Speed;
Vector2 ThrustForce;
float Coefficient = 0.009f;
float PreviousDrag = 0.000f;
//In the update loop
//DeltaTime is a float based upon how much of a second passed
Vector2 AccelerationToApply = ThrustForce * DeltaTime + PreviousDrag * DeltaTime;
Vector2 NewSpeed = Speed + AccelerationToApply;
PreviousDrag = Coefficient * NewSpeed * NewSpeed;
Speed = NewSpeed;
通过excel运行这个逻辑,我发现在大致相同的时间我达到相同的近似终端速度,无论我多久(或不)计算速度的变化。