【问题标题】:2D Spaceship movement math2D 宇宙飞船运动数学
【发布时间】:2010-05-23 02:34:58
【问题描述】:

我正在尝试制作一个自上而下的宇宙飞船游戏,并且我希望动作更加逼真。 360度有惯性、重力等。

我的问题是我可以毫无问题地让船以惯性移动 360°,但我需要做的是限制发动机的行驶速度,同时不限制推/拉船的其他力。

因此,如果发动机速度最大为 500 并且船从重力井中前进 1000,则船在发动机开启时不会前进到 1500,但如果指向远离角度的方向,那么它可能会变慢。

对于它的价值,我使用的是Construct,我所需要的只是它的数学运算。

感谢您的帮助,我试图弄清楚这一点会变得光秃。

【问题讨论】:

    标签: math physics


    【解决方案1】:

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

    (关于我的工作 C++ 代码 sn-p 和 running demo [仅限 Windows],请参见下文。)

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

    说明:

    洛伦兹因子的定义,其中v是速度,c是光速:

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

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

    注意:我之前尝试通过玩摩擦设置来解决我的小行星游戏中的类似问题。我在阅读您的问题时提出了这个解决方案^^

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

    更新:这是我的小行星游戏中的代码 sn-p,它使用洛伦兹因子来限制游戏对象的速度。效果很好!

    更新:* 添加了此算法的 downloadable demo(仅限 Windows;从其他平台的源代码构建)。我不确定所有依赖项是否都包含在 zip 中;如果缺少某些东西,请告诉我。玩得开心^^

    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();
        }
    }
    

    【讨论】:

    • 很酷的把戏;我从来没有想过“改变光速”。
    • 很酷的答案! (为原创而升级!)但是(如果我错了,请纠正我)在这个模型中你不能超过你的最大速度,即使你在黑洞或其他东西周围弹射,或者如果一艘拥有更大引擎的船(更高的最大值速度)拖着你。我认为 OP 可能只希望您的引擎可以实现有限的速度。
    • @Dan:要允许“超光速”,仅在施加发动机力时才应用洛伦兹因子。我将物体上的所有力相加并找到净加速度,但每个力都可以单独应用,每个力都有不同的 c! (我认为这可能会导致奇怪的行为,具体取决于施加力的顺序......)
    • 在这种情况下,我认为如果有其他力量将飞船加速到比引擎的“光速”还快的话,你就会遇到问题;那么引擎的洛伦兹因子将变得不确定。当然,您可以使用条件来解决这个问题,但这可能仍然很奇怪。 (实际上可以证明,在真正的狭义相对论中,极限速度不能超过一个。)
    • 抱歉我的无知,但“/=”是什么意思?
    【解决方案2】:

    好吧,让我们先考虑现实问题,看看为什么这不起作用,以及我们必须如何与之不同。在太空中,只要你的引擎在点火,你就会加速。你的速度只受燃料的限制(事实上,一旦你消耗了一些燃料,你就可以更快地加速,因为你移动的质量较小)。

    要为该模型提供有效的最大速度,您可以考虑空间中的粒子会减慢您的速度并造成摩擦。你走得越快,你击中的粒子越多,你击中它们的速度就越快,所以最终以足够快的速度,你将击中足够多的粒子,它们所做的减速量正好抵消了你的引擎加速的量正在做。

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

    这让我们在达到一定速度时将引擎的有效力降低到 0。现在请记住,如果您在北方向达到最大速度,您仍然希望力能够将您推向东方向,因此您的引擎不应该仅通过原始速度来切断,而是基于您的速度朝着你的引擎指向的方向前进。

    所以,对于数学:

    你想在你的引擎指向向量和你的速度向量之间做一个 cross 点积,以获得引擎指向的方向上的有效速度。一旦你有了这个速度,比如说,125 mph(最大速度为 150),你就可以将你的引擎施加的力缩减到 (150-125)/150*(引擎的力)。

    这将极大地改变你需要多长时间才能加速到全速的速度图。当您接近全速时,您的引擎变得越来越不强大。测试一下,看看它是否是你想要的。另一种方法是,如果点积 >=150,则只说 Force of Engines = 0,否则就是全力。这将允许您线性加速到最大速度,但不能再进一步。

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

    【讨论】:

    • 点积,不是叉积。此外,限制最大速度的想法是一个巧妙的想法,但对我来说,狭义相对论似乎是显而易见的方法。不过,我认为这可能比 OP 想要的更详细的物理学。
    • 谢谢,我试过了,但我遇到了一个问题,当角度改变时(为了简单起见,我们只说 180 度),引擎永远不会扩大到全力。所以,如果速度为 150,角度为 0,则发动机的力为 0,但当船转身时,它仍然为 0,但需要回到 150。所以我需要一些方法来计算船在某个角度的速度,我猜?对不起,如果我很迟钝,谢谢你的帮助!
    • 摩擦力可能是解决这个问题的最简单方法。使它们与速度的大小成比例,并调整它们的强度以限制船可以达到的速度。不要担心现实主义;您已经说过您没有尝试过,并且太空中有(非常微弱的)气体可以提供摩擦力。当然,如果这是一个真正真实的模型,那么您必须考虑到气体流动并且实际上是恒星系统内快速移动的等离子体(太阳风)这一事实。 :-)
    • 什么粒子,什么空间摩擦?好吧,除了他飞进星云:)。真的,这是来自物理学的其他部分。空间密度可以忽略不计。
    • @David 谢谢...我以前从来没有划掉十字架这个词。似乎合适。
    【解决方案3】:

    我真的很喜欢 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的测试小于大于零。

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

        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% 的差异,但我认为这样的代码更简单。

    【讨论】:

      【解决方案4】:

      您需要为您的飞船设置三个变量,您可以根据作用在其上的力在每个物理时间步更新这些变量。这些将是质量、位置和速度。 (请注意,位置和速度是单个数字,而是向量)。在每个物理时间步,您根据速度更新位置,并根据加速度更新速度。您根据作用在船上的力(重力、摩擦力、发动机)计算加速度

      牛顿的力方程是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()
      

      【讨论】:

      • 我对你正在使用的这个游戏创作者一无所知,但如果它没有内置物理引擎,它作为一个游戏创作者很糟糕。也许它有一个,看看它。
      • Construct 实现了牛顿游戏动力学 (newtondynamics.com/forum/newton.php)。我认为@YAS 可能正在使用它,因为他/她只需要数学(您正确提供)。
      • 这只是牛顿方程的普通实现;它不会像 YAS 所要求的那样以任何方式限制速度。
      • @Thomas 如果您假设发动机以最大力爆破并且假设船的重量是恒定的并且具有一定的摩擦系数,那么您最终会在某个最大速度下停止加速(在这个模型中,您不能仅靠引擎的力量就可以超越它……但是可以用黑洞或其他东西来抛射,这就是OP想要的)。虽然“最大速度”不是输入之一,但在了解船舶发动机功率后,您可以通过更改您正在使用的摩擦系数来获得任何您想要的最大速度。
      【解决方案5】:

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

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

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

      您的船应该存储自己的发动机力、加速度和速度。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-06-06
        • 2011-01-30
        • 2012-12-14
        • 2021-07-27
        • 2013-12-07
        • 2011-03-04
        • 2010-10-24
        相关资源
        最近更新 更多