简单的基于物理的运动 [英] Simple physics-based movement

查看:28
本文介绍了简单的基于物理的运动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一款 2D 游戏,我正在尝试使用一些基本的物理代码将对象加速到最高速度.

I'm working on a 2D game where I'm trying to accelerate an object to a top speed using some basic physics code.

这是它的伪代码:


const float acceleration = 0.02f;
const float friction     = 0.8f;  // value is always 0.0..1.0
      float velocity     = 0;
      float position     = 0;

move()
{
   velocity += acceleration;
   velocity *= friction;
   position += velocity;
}

这是一种非常简化的方法,不依赖于质量或实际摩擦力(代码中的摩擦力只是一种作用于运动的通用力).它适用于速度*=摩擦力;"部分防止速度超过某个点.然而,正是这个最高速度及其与加速度和摩擦力的关系让我有点迷失.

This is a very simplified approach that doesn't rely on mass or actual friction (the in-code friction is just a generic force acting against movement). It works well as the "velocity *= friction;" part keeps the velocity from going past a certain point. However, it's this top speed and its relationship to the acceleration and friction where I'm a bit lost.

我想要做的是设置一个最高速度,以及达到它所需的时间,然后使用它们来推导出加速度和摩擦值.

What I'd like to do is set a top speed, and the amount of time it takes to reach it, then use them to derive the acceleration and friction values.


const float max_velocity = 2.0; 
const int   ticks;       = 120; // If my game runs at 60 FPS, I'd like a 
                                // moving object to reach max_velocity in 
                                // exactly 2 seconds.
const float acceleration = ?
const float friction     = ?

推荐答案

我发现这个问题很有趣,因为我最近做了一些关于带阻力的弹丸运动建模的工作.

I found this question very interesting since I had recently done some work on modeling projectile motion with drag.

第 1 点:您实际上是在使用 更新位置和速度显式/前向欧拉迭代,其中状态的每个新值都应该是旧值的函数.在这种情况下,您应该更新位置,然后更新速度.

Point 1: You are essentially updating the position and velocity using an explicit/forward Euler iteration where each new value for the states should be a function of the old values. In such a case, you should be updating the position first, then updating the velocity.

第 2 点:对于阻力摩擦的影响有更真实的物理模型.一种模型(由 Adam Liss 提出)涉及的阻力与速度(称为斯托克斯阻力,通常适用于低速情况).我之前建议的阻力与速度的平方成正比(称为二次阻力,通常适用于高速情况).我将针对您如何推导出最大速度和有效达到最大速度所需的时间的公式,逐一说明.我将放弃完整的推导,因为它们相当复杂.

Point 2: There are more realistic physics models for the effect of drag friction. One model (suggested by Adam Liss) involves a drag force that is proportional to the velocity (known as Stokes' drag, which generally applies to low velocity situations). The one I previously suggested involves a drag force that is proportional to the square of the velocity (known as quadratic drag, which generally applies to high velocity situations). I'll address each one with regard to how you would deduce formulas for the maximum velocity and the time required to effectively reach the maximum velocity. I'll forego the complete derivations since they are rather involved.

斯托克斯阻力:

更新速度的方程为:

velocity += acceleration - friction*velocity

表示如下微分方程:

dv/dt = a - f*v

使用这个积分表中的第一项,我们可以找到解决方案(假设在 t = 0 时 v = 0):

Using the first entry in this integral table, we can find the solution (assuming v = 0 at t = 0):

v = (a/f) - (a/f)*exp(-f*t)

当 t >> 0 时出现最大(即终端)速度,因此方程中的第二项非常接近于零,并且:

The maximum (i.e. terminal) velocity occurs when t >> 0, so that the second term in the equation is very close to zero and:

v_max = a/f

关于达到最大速度所需的时间,请注意方程从未真正达到它,而是向它渐近.然而,当指数的参数等于 -5 时,速度约为最大速度的 98%,可能足够接近以将其视为相等.然后,您可以将达到最大速度的时间近似为:

Regarding the time needed to reach the maximum velocity, note that the equation never truly reaches it, but instead asymptotes towards it. However, when the argument of the exponential equals -5, the velocity is around 98% of the maximum velocity, probably close enough to consider it equal. You can then approximate the time to maximum velocity as:

t_max = 5/f

然后您可以使用这两个方程来求解 fa 给定所需的 vmaxtmax.

You can then use these two equations to solve for f and a given a desired vmax and tmax.

二次阻力:

更新速度的方程为:

velocity += acceleration - friction*velocity*velocity

表示如下微分方程:

dv/dt = a - f*v^2

使用这个积分表中的第一项,我们可以找到解决方案(假设在 t = 0 时 v = 0):

Using the first entry in this integral table, we can find the solution (assuming v = 0 at t = 0):

v = sqrt(a/f)*(exp(2*sqrt(a*f)*t) - 1)/(exp(2*sqrt(a*f)*t) + 1)

当 t >> 0 时出现最大(即终端)速度,因此指数项远大于 1,方程接近:

The maximum (i.e. terminal) velocity occurs when t >> 0, so that the exponential terms are much greater than 1 and the equation approaches:

v_max = sqrt(a/f)

关于达到最大速度所需的时间,请注意方程从未真正达到它,而是向它渐近.然而,当指数的参数等于 5 时,速度约为最大速度的 99%,可能足够接近以将其视为相等.然后,您可以将达到最大速度的时间近似为:

Regarding the time needed to reach the maximum velocity, note that the equation never truly reaches it, but instead asymptotes towards it. However, when the argument of the exponential equals 5, the velocity is around 99% of the maximum velocity, probably close enough to consider it equal. You can then approximate the time to maximum velocity as:

t_max = 2.5/sqrt(a*f)

这也相当于:

t_max = 2.5/(f*v_max)

对于所需的 vmaxtmaxtmax 的第二个等式会告诉您 f 应该是什么,然后您可以将其代入 vmax 的方程以获得 a 的值.

For a desired vmax and tmax, the second equation for tmax will tell you what f should be, and then you can plug that in to the equation for vmax to get the value for a.

这看起来有点矫枉过正,但这些实际上是一些最简单的模拟阻力的方法!任何真正想要查看集成步骤的人都可以给我发送电子邮件,我会将它们发送给您.他们有点过于复杂,无法在这里打字.

This seems like a bit of overkill, but these are actually some of the simplest ways to model drag! Anyone who really wants to see the integration steps can shoot me an email and I'll send them to you. They are a bit too involved to type here.

另一点:我没有立即意识到这一点,但如果您使用我为 v(t).如果您只是对静止加速进行建模,并且您正在跟踪自加速开始以来的时间,则代码将如下所示:

Another Point: I didn't immediately realize this, but the updating of the velocity is not necessary anymore if you instead use the formulas I derived for v(t). If you are simply modeling acceleration from rest, and you are keeping track of the time since the acceleration began, the code would look something like:

position += velocity_function(timeSinceStart)

其中velocity_function"是 v(t) 的两个公式之一,您将不再需要速度变量.一般来说,这里有一个权衡:计算 v(t) 可能比简单地用迭代方案更新速度更昂贵(由于指数项),但它保证保持不变稳定且有界.在某些条件下(例如试图获得一个非常短的 tmax),迭代可能会变得不稳定和爆炸,这是前向欧拉方法的常见问题.但是,保持对变量的限制(如 0 <f <1),应该可以防止这些不稳定性.

where "velocity_function" is one of the two formulas for v(t) and you would no longer need a velocity variable. In general, there is a trade-off here: calculating v(t) may be more computationally expensive than simply updating velocity with an iterative scheme (due to the exponential terms), but it is guaranteed to remain stable and bounded. Under certain conditions (like trying to get a very short tmax), the iteration can become unstable and blow-up, a common problem with the forward Euler method. However, maintaining limits on the variables (like 0 < f < 1), should prevent these instabilities.

另外,如果你觉得有点受虐狂,你可以整合v(t)的公式来得到p(t)的封闭形式解strong>,因此完全不需要牛顿迭代.我会把这个留给其他人尝试.=)

In addition, if you're feeling somewhat masochistic, you may be able to integrate the formula for v(t) to get a closed form solution for p(t), thus foregoing the need for a Newton iteration altogether. I'll leave this for others to attempt. =)

这篇关于简单的基于物理的运动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆