The maths behind shooting at moving targets.

Started by
6 comments, last by glopen 15 years, 10 months ago
First off, I'll switch to a proper vector class as soon as the math bits are sorted out :) According to this logic (which made almost total sense to me), I coded like this to calculate the predicted position of the player and send a bulllet (it's within the enemy class):

	float pl_V[3] ={ player.speed*player.forw[0], player.speed*player.forw[1], player.speed*player.forw[2] };
	float tMINs[3]={ player.x-x, player.y-y, player.z-z }; //target-shooter

	float a= sqr(.3) - dotP(pl_V,pl_V);	//as bullet speed is constant at .3
	float b= -2*dotP(pl_V,tMINs);
	float c= -dotP(tMINs,tMINs);

	float t=(b+sqrt(b*b-4*a*c)/(2*a));     //largest root (I don't know why this is preferred)

	new_targ[0] = player.x + t*pl_V[0];	//calculating predicted position
	new_targ[1] = player.y + t*pl_V[1];
	new_targ[2] = player.z + t*pl_V[2];

	//  Target's predicted: 	 x		y	     z	      bullet's speed
	bullet *p = new bullet(x,y,z, new_targ[0], new_targ[1], new_targ[2],		0.3f, ...);


(Shouldn't it be okay if I just multiply the magnitude of the velocity (player.speed) with the forward (player.forw) vector to attain the player velocity (pl_V)?) From what I understand from the post, the new target should be " player_pos + the displacement of player in time t " which is what " new_targ = player.pos + t*pl_V " is in my opinion doing, while t is the larger root of this equation derived in the post: (s^2-(v.v))*t^2 - (2*((A-B).v))*t - (A-B).(A-B) = 0 //A=target, B=shooter etc. Is this wrong? I applied this to my game it only seems to work when I'm still or the angle between pl_V and targ is small, which is really stupid. The rest of the time this happens: 1. When I'm flying toward the enemy it seems to calculate a larger than necessary value of 't' which means it shoots quite a few units in front of me 2. When I'm about to cross over the enemy it connects a couple of shots and keeps shooting at some point increasingly behind me, which probably means it is underestimating the value of 't'. If anyone has had any experience with this, where am I going wrong? Thanks. [Edited by - glopen on June 18, 2008 10:27:25 PM]
Advertisement
T should be the distance between shooter and new_target divided by bullet speed aka how long it takes the bullet to hit the player. now this makes a cyclic dependency since you don't know where the new target is until you know how far in the future to look, and you don't know how far in the future to look until you know where to measure. You are looking at old targets to calculate T so your times are off a little.
Thanks. I know what you mean and that's probably not the case (just ditched that method this morning). If you take a good look 't' is actually the solution to a quadratic equation that satisfies:

|new_targ - shooter_pos| = bullet_speed*t

And new_targ will be 'player.pos + pl_V*t'. If you take a closer look at the code I posted (or the post I linked to) 't' is defined as the larger solution (dunno why) of the equation. So I do have my 't' right (I think). Maybe I coded it wrong?
well then I mis-interpreted: float targ[3]={ player.x-x, player.y-y, player.z-z };
which is what you use to calculate T which you then use to calculate new_target. Which leads me to the question if targ == new_targ why calculate new_targ?
Quote:
|new_targ - shooter_pos| = bullet_speed*t

Which you then use to calculate new_targ so how does that work again? The easiest way to do it correctly is going to be iterative generate player positions and test shot travel at time t to see if it intersects the position point.
I wrote the post you linked to. You need to do all the computations in a reference frame where the shooter is not moving. If you don't, funny things will happen.

If you can capture a specific example where the bullet is not being shot to the right place, post all the numbers so we can go through the computations by hand.
@stonemetal:
float targ[3] was wrongly named and I've now changed it to tMINs[3] which is equivalent to vector (A-B) or (target-shooter) in alvaro's post that I linked to (check it out if you haven't). It's not the new_target. Otherwise I don't know what you're getting at.

@alvaro:
"You need to do all the computations in a reference frame where the shooter is not moving."
By that do you mean the shooter is always at (0,0,0) i.e. the |B| in your post is always 0? If not, isn't it okay to just calculate everything relative to (0,0,0) neglecting the shooter velocity?

Here's the main problem: the bullets definitely leads the target for most of the time way in front of the target and eventually a couple of bullets will hit if I don't alter my direction. After that the bullets trail the target. It misses 99% of the time but it's guaranteed to hit the target at least once if it (the target) doesn't change its direction.

Is there anything explicitly wrong in my code? Mathematically? Thanks.
Quote:Original post by glopen
@alvaro:
"You need to do all the computations in a reference frame where the shooter is not moving."
By that do you mean the shooter is always at (0,0,0) i.e. the |B| in your post is always 0?

No, I mean what I say. And I said it at the beginning of that post too: I did all the computations in a reference frame in which the shooter is not moving. If this is not your case, change your coordinates so it is. While you are at it, you can make B be 0 if you want, and it might simplify your computations a bit, but I didn't assume that you had done that.

[EDIT: Probably all you have to do is subtract the shooter's velocity from pl_V, but I haven't studied the code carefully]

Again, an example with specific numbers would make it much easier to discuss the Math or the code.
Thanks everyone (esp. alvaro :)) for answering and it really helped me rethink about the theory carefully. And I think I've 'got' it now. Apparently I had coded everything properly but used the wrong velocity vector (pl_V, not that there's anything wrong with the code I posted). I'm actually using the opposite of the forward vector as my forward vector so I should've negated all the values in pl_V before doing the calculations. I did it and whoa! Everything hits! Sorry for being an idiot and thanks again :)

[Took half a day and three different methods before it finally 'occurred' to me "Hey, why isn't my velocity negated?!". It's twice in as many days that some totally stupid code ruined everything.]

This topic is closed to new replies.

Advertisement