c# - 如何使流体阻力方程不依赖于帧速率

标签 c# xna xna-4.0 game-physics

我正在尝试规划一款我开始编码的游戏。 (一开始就很重要)

我的问题是,我希望所有游戏对象的加速/移动部分基于加速力与阻力(从而导致最终速度作为可用速度的上限)

虽然我可以走另一条路,但如果可能的话我宁愿不走。此外,(一位 friend )建议我可以使用物理库,但这似乎有点过分了,此外,我想自己学习和理解这些概念 - 我总是觉得当我更好地理解我自己的程序时做。

我正在制作一个 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 时,最终的速度计算如下(代码来 self 的头脑 - 不是来自 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;

这就是数学问题。问题如下:

应该如何表达才能使其与帧速率无关?

最佳答案

经典方法是独立于游戏循环帧速率来步进模拟物理时间,如果需要推进物理,则计算每帧的多个子迭代。这允许您控制时间步长(通常使其小于主帧速率),这也有助于控制其他潜在不稳定的计算(例如振荡器)。这当然意味着您的物理计算速度必须比实际速度更快所选固定时间步长的时间,否则您的世界将进入慢动作。

说到不稳定性,我想您会在当前的实现中看到一些振荡效应,具体取决于您是否在给定的时间步长内超出了终端速度。解决此问题的一种方法是通过分析积分来计算速度,而不是使用增量步骤进行近似。为此,请将您的公式表示为微分方程,并查看它是否具有易于解析求解的形式。

关于c# - 如何使流体阻力方程不依赖于帧速率,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8041431/

相关文章:

XNA - 使用本地配置文件登录

c# - 将来自单独 API 的结果连接在一起

c# - 如果在异步等待后引发,为什么 ThreadAbortException 不会自动重新抛出?

c# - 创建缩略图

xna - 在 Delphi Prism 中做 XNA

xna - 将 Sprite 限制在特定路径上?

c# - 尝试在字符串中查找单个字符的更快方法是什么?

c# - 如何将实时视频从 WP7 相机流式传输到 XNA 应用程序?

xna - 在 XNA 中缩放整个屏幕

c# - 错误的 IF 语句