我已经阅读了 stackexchange 上的其他几个解决方案,但没有找到解决这个问题的直接解决方案。
我有一个 sourcePoint 和 targetPoint。目标有一个 targetVelocity(速度和方向),源有一个 sourceSpeed。
我需要一种方法来计算 sourceDirection(使用 sourceSpeed 变成 sourceVelocity)
我一直在看数学,它一定是某种等式,函数有时可能会返回 false,即。子弹追不上目标,取决于targetVelocity和sourceSpeed
我目前的解决方案给出了一个方向,但没有考虑到达目标所需的额外长度,因为它基于射击时目标的长度。
另外,如果我能避免 Sqrt/Normalize 这对性能来说会很好,但我正在寻找相当简单/优雅的解决方案。
/// Returns sourceVelocity
public static Vector2 calcBullet(Vector2 source, float sourceSpeed, Vector2 target, Vector2 targetVelocity)
{
var diff = target - source;
var dist = Vector2.Distance(diff, Vector2.Zero);
diff += targetVelocity * (dist / sourceSpeed);
diff.Normalize();
return diff * sourceSpeed;
}
请您参考如下方法:
如果 sourceSpeed 大于 targetSpeed(targetVelocity 的大小),则总是至少有一个解。如果 sourceSpeed 小于或等于 targetSpeed,则可能有也可能没有任何解。
您可以通过目标到达那里所需的时间 t 来参数化目标的路径。您想求解一个等式(结果是二次方程),以获得子弹到达那里所需的时间 (distance(t)/sourceSpeed) 与目标到达所需的时间 t 之间的相等性,以及只有非负 t 的解才有效。
distance(t) = magnitude(target + t*targetVelocity - source)
= sqrt((target.x-source.x + t*targetVelocity.x)^2 + (target.y-source.y + t*targetVelocity.y)^2)
= sqrt(quadratic(t))
那么,你要解决
t = sqrt(quadratic(t))/sourceSpeed
t* sourceSpeed = sqrt(quadratic(t))
t^2 * sourceSpeed^2 = quadratic(t)
如果 t^2 项取消(当目标速度等于源速度时发生),您将得到一个线性方程(如果您尝试使用二次公式,它将给您除以 0)。否则,您会得到一个可以使用二次公式求解的二次方程,尽管您应该在尝试求平方根之前检查判别式 b^2-4ac 是否为负。如果判别式为负,则无解。只有非负实数解才能让您射中目标。
如果有两个正实数解,你必须选择一个。一旦找到正确的 t 值 t_solution,您就会知道目标的位置,(target + t_solution * targetVelocity),并且您可以从源头瞄准那个方向。