lua - 宇宙飞船的二维轨迹规划与物理

标签 lua 2d physics box2d

我正在用太空中的飞船实现一个 2D 游戏。

为了做到这一点,我使用了 LÖVE,它用 Lua 包装了 Box2D。但我相信我的问题可以由比我更了解物理学的任何人回答 - 因此伪代码被接受作为回应。

我的问题是我不知道如何在支持 2D 物理的世界中正确移动我的飞船。更具体地说:

质量的船m位于初始位置{x, y} .它的初始速度矢量为 {vx, vy} (可以是 {0,0} )。

目标是 {xo,yo} 中的一个点.船必须以 {vxo, vyo} 的速度到达目标(或靠近它),遵循最短的轨迹。

有一个函数叫 update(dt)被频繁调用(即每秒 30 次)。在此功能上,船舶可以通过向自身施加“脉冲”来修改其位置和轨迹。脉冲的大小是二元的:您可以在给定方向上应用它,也可以根本不应用它)。在代码中,它看起来像这样:

function Ship:update(dt)
  m = self:getMass()
  x,y = self:getPosition()
  vx,vy = self:getLinearVelocity()
  xo,yo = self:getTargetPosition()
  vxo,vyo = self:getTargetVelocity()
  thrust = self:getThrust()

  if(???)
    angle = ???
    self:applyImpulse(math.sin(angle)*thrust, math.cos(angle)*thrust))
  end
end

第一???是否表明在某些情况下(我猜)最好“不要冲动”并让船“漂移”。第二个???部分包括如何计算给定 dt 上的脉冲角。

我们在太空中,所以我们可以忽略空气摩擦之类的东西。

虽然这会很好,但我不是在找人为我编写代码;我把代码放在那里,所以我的问题很清楚。

我需要的是一种策略——一种解决这个问题的方法。我知道一些基本的物理,但我不是专家。例如,这个问题有名字吗?那种东西。

非常感谢。

编辑:测试版为此提供了一个有效的策略,法官在评论中直接在 LÖVE 中实现了它。

EDIT2:经过更多的谷歌搜索,我还发现了 openSteer .它在 C++ 上,但它做了我假装的。这可能对任何提出这个问题的人都有帮助。

最佳答案

这就是所谓的运动规划,它不是微不足道的。

这是获得非最佳轨迹的简单方法:

  • 停止。施加与速度方向相反的推力,直到速度为零。
  • 计算最后一条腿,这将与第一条腿相反,从站立开始的稳定推力使船到达 x0 和 v0。起点与 x0 的距离为 |v0|^2/(2*thrust)。
  • 到达那个起点(然后进行最后一站)。从一个站立点到另一个站立点很容易:朝它猛推直到你走到一半,然后向后猛推直到你停下来。

  • 如果您想要快速而肮脏的方法来获得最佳轨迹,您可以使用迭代方法:从上面的非最佳方法开始;这只是推力角的时间序列。现在尝试对该序列做一些小的变化,保持一组接近目标的序列。拒绝最糟糕的,尝试最好的——如果你觉得大胆,你可以把它变成一个遗传算法——幸运的是它会开始转角。

    如果您想要确切的答案,请使用变分法。我会尝试一下,如果我成功了,我会在这里发布答案。

    编辑:这是一个更简单问题的确切解决方案。

    假设我们有四个固定的推进器,而不是我们可以指向任何方向的推力,而是指向 {+X, +Y, -X, -Y} 方向。在任何给定时间,我们最多会触发 +/-X 之一和最多 +/-Y 之一(同时触发 +x 和 -X 没有意义)。所以现在 X 和 Y 问题是独立的(它们不在原始问题中,因为推力必须在 X 和 Y 之间共享)。我们现在必须解决一维问题——并应用它两次。

    事实证明,最好的轨迹包括向一个方向推进,然后向另一个方向推进,并且不再回到第一个方向。 (仅当另一个轴的解决方案花费的时间比您的解决方案长,因此您有时间解决时,惯性运动才有用。)首先解决速度问题:假设(WLOG)您的目标速度大于您的初始速度。要达到目标速度,您需要一段时间的推力 (+) 持续时间
    T = (Vf - Vi)/a
    

    (我使用的是 Vf:最终速度,Vi:初始速度,a:推力的大小。)

    我们注意到,如果我们只做这些,位置就不会正确。实际最终位置将是
    X = (Vi + Vf)T/2
    

    所以我们必须添加一个更正
    D = Xf - X = Xf -(Vi+Vf)T/2
    

    现在为了使位置正确,我们在此之前在一个方向上添加一段时间的推力,然后在相反方向上添加一个相等的周期。这将使最终速度不受干扰,但会给我们一些位移。如果第一个(和第三个)周期的持续时间是 t,那么我们从中得到的位移是
    d = +/-(at^2 + atT)
    

    +/- 取决于我们是先推 + 然后 - 还是 - 然后 +。假设它是+。
    我们求解二次方程:
    t = (-aT + sqrt(a^2 T^2 + 4 a D))/2a
    

    我们已经完成了。

    关于lua - 宇宙飞船的二维轨迹规划与物理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2560817/

    相关文章:

    c - 如何修改传递给函数的二维数组

    c++ - 阵列中的涡流场

    lua - 从 Common Lisp 调用 Lua

    lua - 如何检查脚本是否通过dofile()包含或直接在Lua中运行? [复制]

    python - 为什么我的 pygame 应用程序循环不能正常工作?

    algorithm - 如何找到二维长区域的中心线

    django - Openresty : pass a request to FastCGI if data does not found in redis cache 中带有 nginx 的 Lua

    c++ - 如何在 SWIG 中包装使用引用自定义类型的 C++ 函数?

    c++ - 让球落在平面的边缘

    Python:波的可视化