5

假设我有一艘宇宙飞船(source);一颗小行星 ( target) 在它附近的某个地方。

我知道,在 3D 空间(XYZ 向量)中:

  • 我的船的位置( sourcePos) 和速度( sourceVel)。
  • 小行星的位置( targetPos) 和速度( targetVel)。

(例如sourcePos= [30, 20, 10]; sourceVel= [30, 20, 10]; targetPos= [600, 400, 200]; targetVel= [300, 200, 100]`)

我也知道:

  • 船的速度恒定的。
  • 小行星的速度恒定的。
  • 我的船的弹丸速度( projSpd) 是恒定的。
  • 我的船的弹道在被击中后是线性的(/straight)。

(例如projSpd= 2000.00)

我如何计算为了击中小行星而需要射击的拦截坐标?


笔记:

此问题基于此 Yahoo-Answers 页面

我还在 Google 和 SO 上搜索了类似的问题,但大多数答案都是针对 2D 空间的,并且在少数针对 3D 的答案中,解释和伪代码都没有解释正在做什么和/或为什么,所以我无法真正理解到成功地将它们应用到我的代码上。以下是我访问的一些页面:

Danik Games 开发日志Blitz3D 论坛线程UnityAnswersStackOverflow #1StackOverflow #2


我真的无法弄清楚链接页面上的数学/执行流程,除非有人(进一步)剖析它在做什么,以及为什么;
提供一个正确注释的伪代码供我遵循;
或者至少指向我的链接,这些链接实际上解释了方程是如何工作的,而不是仅仅在我已经困惑的心灵中抛出更多的随机数和无法遵循的方程。

4

3 回答 3

12

我发现解决这类问题的最简单方法是首先理解它们,并且具有基本的高中数学水平也会有所帮助。

解决这个问题本质上是求解具有 2 个您不知道的变量的 2 个方程:

  1. 你想为你的射弹找到的矢量 ( V)
  2. 影响时间 ( t)

你知道的变量是:

  1. 目标位置 ( P0)
  2. 目标向量 ( V0)
  3. 目标速度 ( s0)
  4. 弹丸的来源 ( P1)
  5. 弹丸速度 ( s1)

好的,所以第一个等式是基本的。目标和弹丸的落点相同。它等于两个对象的起点+沿它们两个向量的线的一定长度。该长度由它们各自的速度和撞击时间表示。这是等式:

P0 + (t * s0 * V0) = P1 + (t * s0 * V)

请注意,这里缺少两个变量 - V& t,因此我们现在无法求解这个方程。进入第二个等式。

第二个等式也很直观。撞击点与弹丸原点的距离等于弹丸的速度乘以经过的时间:

我们将从第一个等式中对影响点进行数学表达式:

P0 + (t * s0 * V0) <-- point of impact

原点是P1 这两者之间的距离必须等于弹丸的速度乘以经过的时间(distance = speed * time)

距离的公式是:(x0 - x1)^2 + (y0 - y1)^2 = distance^2,因此等式将如下所示:

((P0.x + s0 * t * V0.x) - P1.x)^2 + ((P0.y + s0 * t * V0.y) - P1.y)^2 = (s1 * t)^2 

(您可以轻松地将其扩展为 3 个维度)

请注意,在这里,您有一个只有一个未知变量的方程:t!。我们可以在这里发现t是什么,然后将其放在前面的等式中并找到向量V

让我通过为你打开这个公式来解决你的一些痛苦(如果你真的想,你可以自己做)。

a = (V0.x * V0.x) + (V0.y * V0.y) - (s1 * s1)
b = 2 * ((P0.x * V0.x) + (P0.y * V0.y) - (P1.x * V0.x) - (P1.y * V0.y))
c = (P0.x * P0.x) + (P0.y * P0.y) + (P1.x * P1.x) + (P1.y * P1.y) - (2 * P1.x * P0.x) - (2 * P1.y * P0.y)

t1 = (-b + sqrt((b * b) - (4 * a * c))) / (2 * a)
t2 = (-b - sqrt((b * b) - (4 * a * c))) / (2 * a)

现在,请注意 - 我们将在这里获得 2 个值t

一个或两个可能是负数或无效数字。显然,由于t表示时间,并且时间不能为无效或负数,因此您需要丢弃t.

很可能两者t都不好(在这种情况下,射弹无法击中目标,因为它更快且超出范围)。也可能是两者t都是有效且积极的,在这种情况下,您需要选择两者中较小的一个(因为最好早点而不是晚点达到目标)。

t = smallestWhichIsntNegativeOrNan(t1, t2)

现在我们已经找到了撞击的时间,让我们找出弹丸应该飞行的方向。回到我们的第一个方程:

P0 + (t * s0 * V0) = P1 + (t * s0 * V)

现在,t不再是缺少的变量,所以我们可以很容易地解决这个问题。只需整理方程以隔离V

V = (P0 - P1 + (t * s0 * V0)) / (t * s1)
V.x = (P0.x - P1.x + (t * s0 * V0.x)) / (t * s1) 
V.y = (P0.y - P1.y + (t * s0 * V0.y)) / (t * s1) 

就是这样,你完成了!将向量分配V给射弹,它将到达目标所在的位置,而不是现在的位置。

我真的很喜欢这个问题,因为它需要我们在高中学习的数学方程,每个人都说“为什么要学习这个??我们永远不会在我们的生活中使用它!!”,并为它们提供了一个非常棒且实用的应用程序。

我希望这对您或其他任何试图解决此问题的人有所帮助。

于 2014-03-01T16:32:59.180 回答
2

我有一个解决方案。请注意,船的位置和小行星线(位置和速度)定义了一个 3D 平面,拦截点所在的位置。在我的符号中,下面| [x,y,z] |表示向量或 的大小Sqrt(x^2+y^2+z^2)

请注意,如果小行星与targetSpd = |[300,200,100]| = 374.17then 一起到达拦截点(仍然未知,称为hitPos)将需要等于 的时间t = |hitPos-targetPos|/targetSpd。这是弹丸需要到达拦截点的同一时间,或t = |hitPos - sourcePos|/projSpd。这两个方程用于求解截距时间

t = |targetPos-sourcePos|/(projSpd - targetSpd)
  = |[600,400,200]-[30,20,10]|/(2000 - |[300,200,100]|)
  = 710.81 / ( 2000-374.17 ) = 0.4372

现在 inteception 点的位置由

hitPos = targetPos + targetVel * t
       = [600,400,200] + [300,200,100] * 0.4372
       = [731.18, 487.45, 243.73 ]

现在我知道了命中位置,我可以计算出射弹的方向为

projDir = (hitPos-sourcePos)/|hitPos-sourcePos|
        = [701.17, 467.45, 233.73]/874.52 = [0.8018, 0.5345, 0.2673]

projDir和一起projSpd定义弹丸速度矢量。

于 2013-11-13T19:46:31.407 回答
1

如果你想让一个弹丸击中小行星,它应该在interceptionPos满足等式的点上射击:

|interceptionPos - sourcePos| / |interceptionPos - 目标位置| = projSpd / targetVel
其中|x|是向量的长度x

换句话说,目标和弹丸到达这一点需要相同的时间。
这个问题可以通过几何学和三角学的方式来解决,所以我们来绘制它。 在此处输入图像描述
A将是小行星位置,S - 船,I - 拦截点。在这里,我们有:

AI = targetVel * t
SI = projSpd * t
AS = |targetPos - sourcePos|

矢量 AS 和 AI 方向已定义,因此您可以通过简单的矢量数学轻松计算SAI角度的余弦(从此处此处获取定义)。那么你应该使用余弦定律SAI角度。它将产生一个具有t易于求解的变量的二次方程(无解 = 你的弹丸比小行星慢)。只需选择积极的解决方案t,您的拍摄点将是

targetPos + t * targetVel

我希望你能写一个代码来自己解决它。如果你不能得到什么,请在评论中询问。

于 2013-06-20T12:30:22.513 回答