Настоящая проблема - выяснить, где в космосе пуля может пересекать путь цели. Скорость пули постоянна, поэтому через определенное время она будет перемещаться на одно и то же расстояние независимо от направления, в котором мы ее запускаем. Это означает, что его позиция после времени t всегда будет лежать на сфере. Вот ужасная иллюстрация в 2d:
Эта сфера может быть математически выражена как:
(x-x_b0)^2 + (y-y_b0)^2 + (z-z_b0)^2 = (bulletSpeed * t)^2 (eq 1)
x_b0, y_b0 и z_b0 обозначают положение пушки. Вы можете найти время t, решив это уравнение для t, используя уравнение, приведенное в вашем вопросе:
targetPos+t*targetVelocityVec (eq 2)
(eq 2)
является векторным уравнением и может быть разложено на три отдельных уравнения:
x = x_t0 + t * v_x
y = y_t0 + t * v_y
z = z_t0 + t * v_z
Эти три уравнения можно вставить в (eq 1)
:
(x_t0 + t * v_x - x_b0)^2 + (y_t0 + t * v_y - y_b0)^2 + (z_t0 + t * v_z - z_b0)^2 = (bulletSpeed * t)^2
Это уравнение содержит только известные переменные и может быть решено за t. Присваивая константу постоянную часть квадратичных подвыражений, мы можем упростить вычисление:
c_1 = x_t0 - x_b0
c_2 = y_t0 - y_b0
c_3 = z_t0 - z_b0
(v_b = bulletSpeed)
(t * v_x + c_1)^2 + (t * v_y + c_2)^2 + (t * v_z + c_3)^2 = (v_b * t)^2
Переставьте его как стандартное квадратное уравнение:
(v_x^2+v_y^2+v_z^2-v_b^2)t^2 + 2*(v_x*c_1+v_y*c_2+v_z*c_3)t + (c_1^2+c_2^2+c_3^2) = 0
Это легко разрешимо, используя стандартную формулу. Это может привести к нулю, одному или двум решениям. Нулевые решения (не считая сложных решений) означают, что пуля не может достичь цели. Одно из решений, вероятно, произойдет очень редко, когда целевая траектория пересекается с самым краем сферы. Два решения будут наиболее распространенным сценарием. Отрицательное решение означает, что вы не можете поразить цель, так как вам нужно будет выстрелить в прошлое. Это все условия, которые вы должны проверить.
Когда вы решили уравнение, вы можете найти положение t, вернув его обратно в (eq 2)
. В псевдокоде:
# setup all needed variables
c_1 = x_t0 - x_b0
c_2 = y_t0 - y_b0
c_3 = z_t0 - z_b0
v_b = bulletSpeed
# ... and so on
a = v_x^2+v_y^2+v_z^2-v_b^2
b = 2*(v_x*c_1+v_y*c_2+v_z*c_3)
c = c_1^2+c_2^2+c_3^2
if b^2 < 4*a*c:
# no real solutions
raise error
p = -b/(2*a)
q = sqrt(b^2 - 4*a*c)/(2*a)
t1 = p-q
t2 = p+q
if t1 < 0 and t2 < 0:
# no positive solutions, all possible trajectories are in the past
raise error
# we want to hit it at the earliest possible time
if t1 > t2: t = t2
else: t = t1
# calculate point of collision
x = x_t0 + t * v_x
y = y_t0 + t * v_y
z = z_t0 + t * v_z