1
\$\begingroup\$

I'm having an issue with calculating the predicted linear angle a projectile needs to move in to intersect a moving enemy ship for my 2D game.

I've tried following the document here, but what I've have come up with is simply awful.

protected Vector2 GetPredictedPosition(float angleToEnemy, ShipCompartment origin, ShipCompartment target)
{
    // Below obviously won't compile (document wants a Vector, not sure how to get that from a single float?)
    Vector2 velocity = target.Thrust - 25f; // Closing velocity (25 is example projectile velocity)
    Vector2 distance = target.Position - origin.Position; // Range to close
    double time = distance.Length() / velocity.Length(); // Time

    // Garbage code, doesn't compile, this method is incorrect
    return target.Position + (target.Thrust * time);
}

I would be grateful if the community can help point out how this is done correctly.

\$\endgroup\$

migrated from stackoverflow.com Jun 16 '14 at 13:08

This question came from our site for professional and enthusiast programmers.

  • 1
    \$\begingroup\$ You say "document wants a Vector, not sure how to get that from a single float". A speed (or thrust or velocity) can be expressed with a vector too, because a moving object has a (scalar) speed and a direction (unit vector). If you multiply this unit vector with the speed number, you get a speed vector. It tells you the x and the y component of the speed. \$\endgroup\$ – Olivier Jacot-Descombes Jun 13 '14 at 13:23
3
\$\begingroup\$

Labelling the shooter's position x, the target's initial position y, the speed of the projectile v and the vector velocity of the target dy you must choose a unit vector direction d to shoot in that satisfies the equations

x[0] + v*t*d[0] = y[0] + dy[0]*t
x[1] + v*t*d[1] = y[1] + dy[1]*t

for some time to impact t. Rearranging yields

v*t*d[0] = dy[0]*t + (y[0]-x[0])
v*t*d[1] = dy[1]*t + (y[1]-x[1])

Noting that d is a unit vector we have

d[0]^2 + d[1]^2 == 1

and hence

(v*t)^2 = (dy[0]*t + (y[0]-x[0]))^2 + (dy[1]*t + (y[1]-x[1]))^2
        = dy[0]^2*t^2 + 2*dy[0]*(y[0]-x[0])*t + (y[0]-x[0])^2
        + dy[1]^2*t^2 + 2*dy[1]*(y[1]-x[1])*t + (y[1]-x[1])^2

so

a*t^2 + b*t + c = 0

where

a = v^2 - dy[0]^2 - dy[1]^2
b = -2*dy[0]*(y[0]-x[0]) - 2*dy[1]*(y[1]-x[1])
c = -(y[0]-x[0])^2 - (y[1]-x[1])^2

This is a quadratic equation in t and has solutions

t = (-b +- sqrt(b^2 - 4*a*c)) / (2*a)

If this doesn't have a positive real solution then you can't hit the target (it's moving too fast). If it does, substitute it back into the rearranged equations to get d.
The counter clockwise angle that this makes with the positive x-axis is Math.Atan2(d[1],d[0]) and the difference between it and the angle in which the shooter is facing is the one you're after.

UPDATE: Note that I've assumed that the shooter is stationary. If it's moving and its velocity dx should affect that of the projectile, you need to replace dy[i] with (dy[i]-dx[i]) throughout.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.