0
\$\begingroup\$

I need a bit of help with the maths for a targeting system for a space simulator. The problem is working out the correct turret angle so that the bullets hit the target ship...

I have a ship at location X, Y and the ship has turrets which can turn 360 degrees. I want to aim at an asteroid at location Xa, Ya.

The maths for this which is working great is like this....

VectorX = X - Xa
VectorY = Y - Ya

Angle = (57.2957795 * atan2(VectorX , -VectorY ))

Now consider the asteroid is moving at a velocity vector of Xsa, Ysa and the bullets fired from the turret have a speed.

The maths for this which again works really well is....

VectorX = X - Xa
VectorY = Y - Ya

Distance = sqrt((VectorX * VectorX) + (VectorY * VectorY))

VX = VectorX - (Xsa * (Distance / BulletSpeed));
VY = VectorY - (Ysa * (Distance / BulletSpeed));

Angle = (57.2957795 * atan2( VX, -VY )

Ok the bit I cant get to work right is when the ship is also moving, lets call this velocity vector Xs, Ys. When the ship is moving the bullets fire maintain the movement of the ship plus the bullet firing speed at the angle vector. Think of driving a car and shooting a bullet out the window the bullet would fire out sideways from the car but would also maintain the car's forward momentum as it traveled.

BulletVelX = Xs + ( BulletSpeed * cos( Radians( Angle ) ) )
BulletVelY = Ys + ( BulletSpeed * sin( Radians( Angle ) ) )

I have found a site that says simultaneous equasions could be used to solve the problem but has anyone working knowledge of how this is done.

Thanks

\$\endgroup\$
  • \$\begingroup\$ I don't have an answer to your actual question (I'm not even sure what the question actually is) but a minor note: atan2 is normally defined as taking Y,X not X,Y. \$\endgroup\$ – amitp Aug 2 '16 at 14:20
0
\$\begingroup\$

Your aiming routine seems problematic to begin with. I have no clue where 57.2957795 is coming from.

I guess your atan2 routine takes y as the first parameter not the second and so you needed a correction factor.

Your aiming at a moving target routine is also just an approximation and not the correct math. In order to work this out we will describe where your bullet could be at a given time by a circle and we will describe where the ship you are targeting will be with a line.

//Circles radius depending on t
r(t) = bulletSpeed*t;
//Enemy ships position depending on t
s(t) = (Xa,Ya) + t*(Xsa,Xya)
//We are really just interested in our relative distance though, so
//our distance from the ship at time t is
d(t) = length(s(t)-(X,Y))
//Now we want that distance to be the same as where our bullet can be at time t. So:
   r(t)=d(t)
<->r(t)^2 = d(t)^2
<->bulletSpeed^2*t^2=(s(t).X-X)^2+(s(t).Y-Y)^2
<->bulletSpeed^2*t^2=(Xa-X+t*Xsa)^2+(Ya-Y+t*Ysa)
<->bulletSpeed^2*t^2=(Xa-X)^2+2(Xa-X)*Xsa*t+t^2*Xsa^2+(Ya-Y)^2+2(Ya-Y)*Ysa*t+t^2*Ysa^2
//Now we can take a shortcut here and differentiate this,
//since we are looking for the minimum and it is geometrically clear
//That there is only one minimum if it exists.
<->2*bulletSpeed^2*t=2(Xa-X)*Xsa+2*t*Xsa^2+2*(Ya-Y)*Ysa+2*t*Ysa^2
<->2*bulletSpeed^2*t-2*t*Xsa^2-2*t*Ysa^2 = 2(Xa-X)*Xsa+2(Ya-Y)*Ysa
<->t*(2*bulletSpeed^2-2*Xsa^2-2*Ysa^2) = 2(Xa-X)*Xsa+2(Ya-Y)*Ysa
<->t = ((Xa-X)*Xsa+(Ya-Y)*Ysa)/(bulletSpeed^2-Xsa^2-Ysa^2)
//Now this tells you at what time your bullet and the target could collide
//(Unless I made a mistake in deriving this, which should be easy to check)
//So let's call the t that solves that equation t'.

//If you are moving relative to the thing you are shooting at, consider your own ship at rest.
//And subtract your velocity from the other ships velocity, so you get the relative velocity between both ships.
Xsa = Xsa-Xs
Ysa = Ysa-Ys

//Then 
Diff = s(t')-(X,Y)
Angle = atan2(Diff.Y,Diff.X)
| improve this answer | |
\$\endgroup\$
  • 1
    \$\begingroup\$ @user88213: It would be better to write 57.2957795 as 180/π, or have a function RadiansToDegrees. \$\endgroup\$ – amitp Aug 2 '16 at 14:21
  • \$\begingroup\$ Ah, that makes a lot of sense. \$\endgroup\$ – Nils Ole Timm Aug 2 '16 at 14:48
  • \$\begingroup\$ Yes the * 57.2957795 is to convert from Rads to Degrees. I should have edited my pseudo code to make this more obvious. It's for a mobile game and a calculation that is potentially performed multiple times per frame so I am trying to use the least amount of processing overhead possible. \$\endgroup\$ – Assasinsareus Aug 2 '16 at 16:50
  • \$\begingroup\$ Then why are you converting to an angle at all? You are converting to an angle from a vector then converting back to the vector right away. Also since both 180 and pi are constants your compiler will definitely optimize that division operation away and having 180/pi there will be much more readable. \$\endgroup\$ – Nils Ole Timm Aug 2 '16 at 17:02
  • \$\begingroup\$ The angle controls the arm of the turret gun which can only swing at a certain rate so is required. I have come from embedded programming where the compilers almost certainly wouldn't optimise out two constants and am used to seeing that number by now. \$\endgroup\$ – Assasinsareus Aug 3 '16 at 7:55

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.