Aiming Accurately at Moving Targets

BlitzMax Forums/BlitzMax Programming/Aiming Accurately at Moving Targets

SpaceTW(Posted 2009) [#1]
Hi, I need help aiming at moving targets for a program. I have the variables for the speed and direction of the enemies, but the targeting is still not accurate enough. Here is an example of the code I need corrected:



The ftargetx and y need to properly aim ahead of the enemy so a collision is inevitable for all X and Y speeds. Thanks for any help.


Grey Alien(Posted 2009) [#2]
You need to use a quadratic equation. Google it :-) I used one for a shoot em up I made years ago in DOS.


Warpy(Posted 2009) [#3]
OK! This one took a lot of thinking, and beware that there is a lot of maths involved, but you can just use the formula at the end without too much worry.


Suppose you have a tower at a fixed position (x0,y0), and an enemy at initial position (x1,y1) moving in the direction (vx,vy).

You want to shoot a bullet travelling at a certain velocity (V) so that it collides with the enemy.

Let the direction of the bullet be (dx,dy).

If dx=vx and dy=vy, then the bullet will move in parallel with the enemy, always staying the same distance from it.

You can now consider that the enemy is not moving at all, relative to the bullet, and the distance between them is (x1-x0,y1-y0). The bullet can move along this line to collide with the bullet.

If the bullet takes (t) frames to reach the bullet, we now get:

dx = (x1-x0)/t + vx
dy = (y1-y0)/t + vy

As we said that the bullet's velocity is V, we get

dx^2 + dy^2 = V^2

Which expands out to:

(1/t)^2 * ( (x1-x0)^2 + (y1-y0)^2 ) + (1/t) * 2 * ( vx*(x1-x0) + vy*(y1-y0) ) + vx^2 + vy^2 - V^2 = 0

Which is a quadratic equation! So set:

a = (x1-x0)^2 + (y1-y0)^2
b = 2 * ( vx*(x1-x0) + vy*(y1-y0) )
c = vx^2 + vy^2 - V^2

Then:

1/t = (-b + sqr( b*2 - 4*a*c)) / (2*a)

You can now put that back into the equations for dx and dy, and you're done!



In bmax code:
				dx=e.x-x
				dy=e.y-y
				a:Double=dx*dx+dy*dy
				b:Double=2*(e.speedx*dx+e.speedy*dy)
				v:Double=3
				c:Double=e.speedx*e.speedx+e.speedy*e.speedy-v*v
				tInv#=(-b+Sqr(b*b-4*a*c))/(2*a)
				dx=dx*tInv+e.speedx
				dy=dy*tInv+e.speedy


Hope this helps!


By the way, instead of creating a bullet at (x+15,y+15) and drawing the rectangle at (x,y), you should create a bullet at (x,y) and draw the rectangle at (x-15,y-15), so that (x,y) is always at the centre of your tower, which helps with the aiming.


ImaginaryHuman(Posted 2009) [#4]
Cripes. Seems overly complex. Can't you just monitor and measure the player's current speed and trajectory, extrapolate it to where the player is expected to be at a certain time in the future based on distance to the player, and shoot at that angle? I know that's probably what you're doing but it seems quite complex in the math department.


marksibly(Posted 2009) [#5]
I used to:

1) Calculate x,y velocity for bullet.

2) Add x,y velocity of player.

3) Done!


*(Posted 2009) [#6]
trust mark to give a overly simple version that works ROFL :)


Warpy(Posted 2009) [#7]
ImaginaryHuman: that "certain time" is the tricky bit. If the bullet is going at a certain speed, then there will be only two times at which its path can intesect that of the enemy. That's what the quadratic's about.


Mark's solution doesn't have every bullet going at the same speed, I don't think.


Grey Alien(Posted 2009) [#8]
Quadratic is best :-p and as Warpy has laid it out in BMax code, no reason not to use it :-)


GW(Posted 2009) [#9]
Quadratic is best :-p and as Warpy has laid it out in BMax code, no reason not to use it :-)


plus, what Mark said makes no sense.


Nate the Great(Posted 2009) [#10]
@GW - what mark says makes perfect sense but it will lead to the bullets traveling at different speeds

mark - is this what you are trying to say?

(x0,y0) = tower position
(x1,y1) = enemy position
(vx,vy) = enemy direction/speed vector
(bx,by) = bullet x and y velocities

dist# = sqr((x0-x1)^2 + (y0-y1)^2)
bx = (x1-x0)/dist + vx
by = (y1-y0)/dist + vy



marksibly(Posted 2009) [#11]
> mark - is this what you are trying to say?

Yep - it basically just puts the bullets into the enemy's 'frame of reference'. You may also want to scale bx/by a bit (before adding vx,vy) to make bullets go a bit faster.

The downside is it can make for very fast bullets depending on how fast the enemy can move, but this may be better than bullets fired at a very steep angle that take forever to get there!


Jesse(Posted 2009) [#12]
Warpy, Thanks! That helped me out also.
I think it belongs in the code archives so it won't get lost. :)


Vilu(Posted 2009) [#13]
Warpy, you're a lifesaver. :)

I adapted your snippet for a bit more complex scenario where both the shooter and the target are moving. Also, this one allows the "business end" of the gun to be somewhere else than the center of the rotating shooter.



Now those buggers seem to be dead accurate.