[英]2D: Moving Turret's Projectile Intercept moving target
所以我正在制作太空游戏,宇宙飞船上有炮塔。
那些炮塔需要用恒定速度的弹丸射击移动目标。 AkA 它需要拦截并击中目标。
当我的船和 npc 船不在同一个方向或几乎同一个方向移动时,它工作得很好。 当他们向同一方向移动时,炮塔会在 npc 船的稍后方发射射弹。 但是一旦我转弯,它就会始终如一地击中 npc 船。
另外,当我站着不动时,npc 船在我面前微微开火,但当我站着不动时,我的船一直在撞击 npc 船。
这是我的代码:
Vector2 toTarget = (targetShip.GlobalPosition) - GlobalPosition;
Vector2 targetVel = (targetShip.dir * targetShip.speed);
Vector2 gunVelocity = (Player.currentShip.dir * Player.currentShip.playerSpeed);
Vector2 vr = targetVel - gunVelocity;
float t = AimAhead(toTarget, vr);
if(t > 0f)
{
Vector2 aimPoint = targetShip.GlobalPosition + vr * t;
dir = aimPoint - Player.currentShip.GlobalPosition;
GlobalRotation = Mathf.LerpAngle(GlobalRotation, dir.Angle(), turnRate * delta);
}
else
{
Vector2 aimPoint = targetShip.GlobalPosition;
dir = aimPoint - Player.currentShip.GlobalPosition;
GlobalRotation = Mathf.LerpAngle(GlobalRotation, dir.Angle(), turnRate * delta);
}
前方目标 function:
float a = vr.Dot(vr) - (projectile.speed * projectile.speed );
float b = 2 * vr.Dot(toTarget);
float c = toTarget.Dot(toTarget);
float det = b * b - 4 * a * c;
if (det > 0f)
{
return 2 * c / (Mathf.Sqrt(det) - b);
}
else
{
return -1f;
}
对于简单的线性运动,这看起来是正确的:
float a = vr.Dot(vr) - (projectile.speed * projectile.speed);
float b = 2 * vr.Dot(toTarget);
float c = toTarget.Dot(toTarget);
从那里我会这样做:
var bb = b * b;
var a2 = 2 * a;
var ac4 = 4 * a * c;
并使用此检查:
if (bb >= ac4 && a2 != 0.0)
显然bb >= ac4
等同于您正在使用的支票。
那么为什么a2.= 0.0
? 好吧,如果你猜对了前三行,我想你知道我们正在使用二次方程的解。 一个二次方程有两个解,分别是(-b + sqrt(bb - ac4))/a2
和(-b - sqrt(bb - ac4))/a2
即二次方程的±:
我不想被零除。
好的,所以我们有两种可能的解决方案。 这就是我进行的方式:
var r = Mathf.Sqrt(bb - ac4);
var times = new float[]{(-b + r)/a2, (-b - r)/a2};
var time = float.PositiveInfinity;
foreach (var candidate_time in times)
{
if (candidate_time < 0.0)
{
continue;
}
if (candidate_time < time)
{
time = candidate_time;
}
}
if (float.IsInfinity(time))
{
return -1f;
}
return time;
这是基于击中移动目标的实现,该目标遵循您可以在其他地方找到的线段定义的路径。 对于这个简单的案例,我可以做更多的事情。
啊一个有趣的错误...
Vector2 aimPoint = targetShip.GlobalPosition + vr * t;
应该:
Vector2 aimPoint = targetShip.GlobalPosition + targetVel * t;
现在一切正常。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.