Tuesday, August 18, 2015

mathematics - Algorithm to shoot at a target in a 3d game



For those of you remembering Descent Freespace it had a nice feature to help you aim at the enemy when shooting non-homing missiles or lasers: it showed a crosshair in front of the ship you chased telling you where to shoot in order to hit the moving target.


I tried using the answer from https://stackoverflow.com/questions/4107403/ai-algorithm-to-shoot-at-a-target-in-a-2d-game?lq=1 but it's for 2D so I tried adapting it.


I first decomposed the calculation to solve the intersection point for XoZ plane and saved the x and z coordinates and then solving the intersection point for XoY plane and adding the y coordinate to a final xyz that I then transformed to clipspace and put a texture at those coordinates. But of course it doesn't work as it should or else I wouldn't have posted the question.


From what I notice the after finding x in XoZ plane and the in XoY the x is not the same so something must be wrong.


    float a = ENG_Math.sqr(targetVelocity.x) + ENG_Math.sqr(targetVelocity.y) -
ENG_Math.sqr(projectileSpeed);
float b = 2.0f * (targetVelocity.x * targetPos.x +
targetVelocity.y * targetPos.y);
float c = ENG_Math.sqr(targetPos.x) + ENG_Math.sqr(targetPos.y);
ENG_Math.solveQuadraticEquation(a, b, c, collisionTime);


First time targetVelocity.y is actually targetVelocity.z (the same for targetPos) and the second time it's actually targetVelocity.y.


The final position after XoZ is


    crossPosition.set(minTime * finalEntityVelocity.x + finalTargetPos4D.x, 0.0f, 
minTime * finalEntityVelocity.z + finalTargetPos4D.z);

and after XoY


    crossPosition.y = minTime * finalEntityVelocity.y + finalTargetPos4D.y;

Is my approach of separating into 2 planes and calculating any good? Or for 3D there is a whole different approach?




  • sqr() is square not sqrt - avoiding a confusion.



Answer



There is no need to break it down into 2 2d functions. That quadratic equation you are working with works fine in 3d as well. Here is pseudo code for either 2d or 3d. It implies a tower (tower defense) is shooting the projectile:


Vector totarget =  target.position - tower.position;

float a = Vector.Dot(target.velocity, target.velocity) - (bullet.velocity * bullet.velocity);
float b = 2 * Vector.Dot(target.velocity, totarget);
float c = Vector.Dot(totarget, totarget);


float p = -b / (2 * a);
float q = (float)Math.Sqrt((b * b) - 4 * a * c) / (2 * a);

float t1 = p - q;
float t2 = p + q;
float t;

if (t1 > t2 && t2 > 0)
{

t = t2;
}
else
{
t = t1;
}

Vector aimSpot = target.position + target.velocity * t;
Vector bulletPath = aimSpot - tower.position;
float timeToImpact = bulletPath.Length() / bullet.speed;//speed must be in units per second


'aimSpot' may be the vector you are asking about.


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...