Answers:
假设您希望这是一帧接一帧的东西(目标甚至可能正在移动),而不是预先计算的轨迹,这实际上非常简单:
在每一帧中,将导弹的速度矢量与矢量(位置目标 -位置)进行比较导弹)进行比较;即从导弹指向目标的向量。在每个帧中,如果两个向量的方向不同,则将速度向量向另一个向量旋转一点,这样,在每帧中,导弹的瞄准点都变得更接近目标。
您可以通过查看两个向量之间的叉积符号来确定是顺时针还是逆时针旋转。
[编辑] 类似于XNA的代码(我没有XNA对此进行测试):
//Once a frame:
//Get vector spanning from missile to target
Vector2 vectorToTarget = target.Position - missile.Position;
//Convert to Vector3 to do cross-product
Vector3 vectorToTarget3 = new Vector3(vectorToTarget, 0);
Vector3 missileVelocity3 = new Vector3(missile.Velocity, 0);
//Rotate clockwise/counter-clockwise is determined by sign of cross-product
int crossProductSign = Vector3.Cross(missileVelocity3, vectorToTarget3).Z;
//Positive cross-product means rotate counter-clockwise, negative is clockwise
double rotationAngle = 0;
if(crossProductSign > 0)
rotationAngle = -0.05;
else if(crossProductSign < 0)
rotationAngle = 0.05;
//I'm not sure how to do rotation in XNA, but the internets tell me it's something like this:
missile.velocity = Vector2.Transform(missile.velocity, Matrix.CreateRotationZ(rotationAngle))
请注意,由于rotationAngle
只有三个可能的值,Matrix.CreateRotationZ(rotationAngle)
因此可以缓存所有可能的值,因此您不必在每一帧都调用它。
有两种可能的技术:
第一项技术是基于帧仿真。如果您在做游戏中的类似归巢导弹之类的事情而不必精确地击中目标,那么这很好。
在这种情况下,您要跟踪对象的位置和速度。每帧都看向目标的方向和当前的移动方向,并适当调整速度。
如果您立即捕捉到速度,则导弹将始终击中目标。但是,如果您在每帧中以少量调整速度,则导弹将向目标弯曲-如果弯曲速度足够慢,目标可能会躲避它。
第二种技术是使用参数方法。这对于为希望精确且可预测地达到目标的事物设置动画很有用。在这种情况下,通常将“时间”作为参数,并将其放入某种函数中。
一组特别有用的功能是您在中学物理中学到的运动方程。通过将它们应用于两个轴,您可以获得弹道。只需一点数学,您就可以确定击中目标的初始参数-如果目标可预测,甚至可以移动目标。
XNA还提供许多插值和弯曲运动功能。看看在对文件Vector2
和MathHelper
。这些提供了一些插值函数,您可以使用这些插值函数甚至将它们组合起来以完成有趣的事情。例如,发射导弹:(Lerp
线性内插)导弹的位置从其起始点到目标位置,并将该目标位置从某个初始目标隐蔽到目标对象的真实(变化)位置。这将为您提供良好的“锁定”效果。
(也有某些功能用于产生曲线,例如:CatmulRom
,Hermite
。这些可能是更难与移动目标成功地使用,虽然。)
如果您查看“缓动”(在动画的上下文中),则可以获得一些更有趣的插值函数,这些函数可以给您带来有趣的效果,例如加速。
现在-您可能会说,这种技术在目标移动时会产生一些奇怪的结果。但是实际上,只要弹丸的移动速度快于目标,它通常看起来就很好。如果有问题,您可能仍应使用基于帧的技术。
您可能需要查找正弦波或Bezier曲线。我不知道正弦波方法是否正常,但我看不出为什么会那么差。
您可以看一下Craig Reynolds定义的“转向行为”:http : //red3d.com/cwr/steer/
这通常在AI中使用,以使NPC移向其目标。