2D太空飞船运动数学

时间:2010-05-23 02:34:59

标签: math physics

我正在尝试制作一个自上而下的太空飞船游戏,我希望这个运动有点逼真。 360度惯性,重力等

我的问题是我可以让船在没有问题的情况下以惯性移动360°,但我需要做的是限制发动机的速度,同时不限制推/拉船的其他力。

因此,如果发动机转速最大为500且船舶从重力井转向1000,则当发动机打开时,该船不会进入1500,但如果指向远离角度那么它可能会变慢。

对于它的价值,我正在使用Construct,而我所需要的就是数学。

感谢您提供任何帮助,我试图解决这个问题。“

5 个答案:

答案 0 :(得分:25)

relative physics获取一个页面,其中包含对象cannot exceed the speed of light

(请参阅下面的我正在使用的C ++代码段和running demo [仅限Windows]。)

  1. 将常数c设置为对象可以达到的最大速度(游戏中的“光速”)。
  2. 如果施加力会增加物体的速度,则将加速度(速度变化)除以洛伦兹因子。 if条件在狭义相对论方面是不现实的,但它使船舶在高速时更加“可控”。
  3. 更新:通常情况下,当以接近c的速度行驶时,船舶难以操纵,因为改变方向需要加速度将速度推过c(洛伦兹因子将最终将新加速度的加速度调整到几乎为零。)重新获得机动性,使用速度矢量的方向,没有洛伦兹缩放与缩放速度矢量的大小。
  4. <强>解释

    洛伦兹因子的定义,其中v是速度,c是光速: gamma = 1 / sqrt(1 - v^2 / c^2)

    这是有效的,因为随着速度的增加,洛伦兹因子接近无穷大。物体需要施加无限大的力才能穿过光速。在较低的速度下,洛伦兹因子非常接近1,接近经典的牛顿物理学。

    随着速度的增加洛伦兹因子图:

    alt text

    注意:我之前尝试通过玩摩擦设置来解决我的小行星游戏中的类似问题。当我读到你的问题^^

    时,我想出了这个解决方案

    更新:我尝试实现这一点并发现了一个潜在的缺陷:随着光速c接近,包括减速在内,所有方向的加速都受到限制! (反直觉,但在现实世界中是否会出现相对相对论?)我猜这个算法可以修改以考虑速度和力矢量的方向... 算法已经经过修改以考虑向量的方向,因此船舶不会在高速时“失去控制性”。

    更新:这是我的小行星游戏的代码片段,它使用洛伦兹因子来限制游戏对象的速度。它运作得很好!

    更新:*添加了downloadable demo(仅限Windows;从其他平台的源代码构建)此算法的实施。我不确定是否所有依赖项都包含在压缩;如果遗漏了什么,请告诉我。并且玩得开心^^

    void CObject::applyForces()
    {
        // acceleration: change in velocity due to force f on object with mass m
        vector2f dv = f/m;
    
        // new velocity if acceleration dv applied
        vector2f new_v = v + dv;
    
        // only apply Lorentz factor if acceleration increases speed
        if (new_v.length() > v.length())
        {
            // maximum speed objects may reach (the "speed of light")
            const float c = 4;
    
            float b = 1 - v.length_squared()/(c*c);
            if (b <= 0) b = DBL_MIN;
    
            double lorentz_factor = 1/sqrt(b);
            dv /= lorentz_factor;
        }
    
        // apply acceleration to object's velocity
        v += dv;
    
        // Update:
        // Allow acceleration in the forward direction to change the direction
        // of v by using the direction of new_v (without the Lorentz factor)
        // with the magnitude of v (that applies the Lorentz factor).
        if (v.length() > 0)
        {
            v = new_v.normalized() * v.length();
        }
    }
    

答案 1 :(得分:2)

好吧,让我们首先考虑现实问题,看看为什么这不起作用以及我们如何与之不同。在空间中,只要您的发动机正在发射,您就会加速。你的速度只受你的燃油限制(事实上,一旦你花了一些燃料,你可以加快速度,因为你的移动质量较小)。

为了给这个模型一个有效的最大速度,你可以考虑在空间中的粒子减慢你的速度并引起摩擦。你走得越快,你击中的粒子越多,击中它们的速度就越快,所以最终以足够快的速度击中足够多的粒子,它们的减速量确实抵消了加速你的引擎的速度正在做。

这个逼真的模型听起来并不像你想要的那样。原因是:你必须引入摩擦力。这意味着如果您削减引擎,您将自动开始减速。您可以将此视为您不想要的意外力量之一。

这使我们在达到一定速度时将发动机的有效力减小到0。现在请记住,如果你的北方向最大速度,你仍然希望力能够向东推动你,所以你的发动机不应该只用原始速度切割,而是根据速度你的朝着引擎指向的方向前进。

所以,对于数学:

您希望在引擎指向矢量和速度矢量之间执行 cross 点积,以获得引擎指向方向的有效速度。一旦你有这个速度,比如125英里/小时(最高速度为150),你可以缩小你的发动机的力量,施加到(150-125)/ 150 *(发动机的力)。

这将彻底改变加速到全速所需时间的速度图。当您接近全速时,您的发动机变得越来越不强大。测试一下,看看它是不是你想要的。另一种方法是,如果点积≥150,则说发动力= 0,否则它是全力。这将允许您线性加速到最大速度,但不能再进一步。

现在我想起来了,这个型号并不完美,因为你可以在北方加速到150英里/小时,然后转向东方并加速到150英里/小时,朝这个方向行驶,总共212英里/小时东北方向,所以不是一个完美的解决方案。

答案 2 :(得分:2)

我真的喜欢Wongsungi的答案(使用Lorentz因子),但我想要注意的是,可以简化代码以减少浮点运算。

不是计算洛伦兹因子(它本身是倒数)然后除以它,而是像这样:

        double lorentz_factor = 1/sqrt(b);
        dv /= lorentz_factor;

简单地乘以洛伦兹因子的倒数,如下所示:

        double reciprocal_lorentz_factor = sqrt(b);
        dv *= reciprocal_lorentz_factor;

这消除了代码中的一个浮点运算,并且还消除了将b钳位到DBL_MIN的需要(现在它可以被钳位到0,因为我们不再进行分频)。当你可以乘以 x 时,为什么要除以 x 的倒数?

此外,如果您可以保证 v 的大小永远不会超过 c ,那么您可以消除 b 的测试比零。

最后,您可以在外部sqrt()语句中使用length_squared()而不是length()来消除另外两项if操作:

    if (new_v.length_squared() > v.length_squared())
    {
        const float c = 4;

        float b = 1 - v.length_squared()/(c*c);
        if (b < 0) b = 0;

        double reciprocal_lorentz_factor = sqrt(b);
        dv *= reciprocal_lorentz_factor;
    }

这可能只会使速度有0.1%的差异,但我认为代码更简单。

答案 3 :(得分:1)

您的船只需要有三个变量,您可以根据作用于它的力量在每个物理时间步骤更新。这些将是质量,位置和速度。 (注意位置和速度是单个数字但是矢量)。在每个物理时间步,您可以根据速度更新位置,并根据加速度更新速度。根据作用在船上的力(重力,摩擦力,发动机)计算加速度

牛顿力的等式是F = M*A我们可以将其重新排列为A = F/M以获得加速度。基本上你需要弄清楚船应该加速多少,以及在哪个方向(矢量),然后将该加速度加到船的速度上,并将船的速度加到它的位置。

以下是您应该执行每个物理时间步骤的代码(我希望您可以填写空白)请询问这是否不够详细

gravity = //calculate force of gravity acting on ship from Newton's law of universal gravitation
friction = //ten percent of the ship's velocity vector, in the opposite direction
engines = 0
if (engines_are_firing)
    engines = 500
forces = gravity + friction + engines
acceleration = forces / ship.mass
ship.velocity += acceleration
ship.position += velocity
redraw()

答案 4 :(得分:0)

我很难理解你的问题,但似乎你没有在这个游戏中使用真正的物理。您是否考虑过使用真实物理方程,如速度,加速度,力等?

修改 编辑完成后,我想我有了更好的理解。您只是跟踪当前的速度(或类似的东西),但是您没有跟踪速度来自的力。船舶不应存储任何信息(除了发动机推力) - 它应该来自船舶所处的环境。

例如,环境具有重力矢量(方向力),因此在计算引擎提供的方向力时需要考虑到这一点。

你的船应该存放自己的发动机力,加速度和速度。