# Calculating 2D Physics Prediction of Shot Angle with Moving Velocity of both targets

I currently have the math right to hit a moving target with 99% accuracy as long as I don't move.

When I start moving the aim is nearly 80%, it should also be 99% accuracy because the target is moving with you at a constant speed.

You can't have 100% accuracy even if you are not a moving player because the other target can dodge your bullet when they see it flying near them, the bullet is shot into the future knowing where the target will end up if they keep moving at the same constant X,Y speeds.

I don't seem to understand how to calculate the new shot angle when I am moving with a moving target together.

Each player has 5 variables

1. X Coordinate in Pixels
2. Y Coordinate in Pixels
3. X Speed (can be negative) this is measured in pixels in 10 milliseconds
4. Y Speed (can be negative) this is measured in pixels in 10 milliseconds
5. Bullet Speed (-32768 to 32767) (negative bullet means how fast a shot is backwards) also measured using pixels, number of pixels traveled in 10 seconds.

The calculates are done using 10 milliseconds so all the X,Y's have to be scaled from 10 seconds to 10 milliseconds as well as Bullet Speed which uses the same 10 seconds pixels traveled system.

Weapon Speed of 1000 [Just a base speed for testing]
-----------------------------------------------------------
1000 pixels = 10 seconds                    1000/10 = 100
900 pixels = 9 seconds                      900/9 = 100
...
500 pixels = 5 seconds                      500/5 = 100
100 pixels = 1 second.                      100/1 = 100
50 pixels = 500 milliseconds.               50/500 = 0.1
25 pixels = 250 milliseconds.               25/250 = 0.1
12.5 pixels = 125 milliseconds.             12.5/125 = 0.1
6.25 pixels = 62.5 milliseconds.            6.25/62.5 = 0.1
3.125 pixels = 31.25 milliseconds.          3.125/31.25 = 0.1
1.5625 pixels = 15.625 milliseconds.        1.5625/15.625 = 0.1
0.78125 pixels = 7.8125 milliseconds.       0.78125/7.8125 = 0.1
1 pixel = 10 milliseconds. (seems correct). 1/10 = 0.1
-----------------------------------------------------------
Conclusion How much pixels to travel in time equation is
double PixelsTraveled = (WeaponSpeed / 10,000) * timeSpentInMilliSeconds;


The game does a update every 10 milliseconds to everything.
When the Bullet Speed is 1000 that means it travels 100 pixels per second. (1000/10)=100

Doubt I need to take into account that 10 milliseconds per game update, since when I don't move I never use 10 milliseconds and it works perfect.

EDIT: This thread (outside game loop) actually has a sleep time of 10 milliseconds which cancels out the effect even though it doesn't synchronize the time dot to dot.

Here is the nearly perfect code, 99% accuracy
For myPlayer attacking a moving target when you have X Speed=0, Y Speed=0

double xDelta = targetPlayer.XCoordinate - myPlayer.XCoordinate;
double yDelta = targetPlayer.YCoordinate - myPlayer.YCoordinate;
double targetDistance = sqrt((xDelta*xDelta)+(yDelta*yDelta));

// Prediction of shot.
double impactTime = targetDistance/targetPlayer.BulletSpeed;
xDelta += impactTime*targetPlayer.XSpeed;
yDelta += impactTime*targetPlayer.YSpeed;

// Gets new firing angle.


Here is the code I attempted to make it get a new firing angle when both targets are moving which I have to take into account both player's speeds and bullet speed.
Seems I have over complicated it with sqrt and it doesn't work right.

double xDelta = targetPlayer.XCoordinate - myPlayer.XCoordinate;
double yDelta = targetPlayer.YCoordinate - myPlayer.YCoordinate;
double targetDistance = sqrt((xDelta*xDelta)+(yDelta*yDelta));

// Prediction of shot.
double predictBulletSpeedX = myPlayer.BulletSpeed + myPlayer.XSpeed;
double predictBulletSpeedY = myPlayer.BulletSpeed + myPlayer.YSpeed;
double finalBulletSpeed = sqrt((predictBulletSpeedX*predictBulletSpeedX)+(predictBulletSpeedY*predictBulletSpeedY));
double impactTime = (targetDistance/finalBulletSpeed);

xDelta += impactTime*targetPlayer.XSpeed;
yDelta += impactTime*targetPlayer.YSpeed;

// Gets new firing angle.


After testing a few ideas, I'm focusing on this answer because it is the cleanest code. The algorithm is very similar to your approximation, except I've modified it to iterate to a given accuracy:

double max_error = 0.0000000001; // measured in radians
double dx=targetPlayer.XCoordinate - myPlayer.XCoordinate;
double dy=targetPlayer.YCoordinate - myPlayer.YCoordinate;
double targetDistance = sqrt(dx*dx+dy*dy);
double ImpactTime=targetDistance/myPlayer.BulletSpeed;
int max_iterations = 100;
while (max_iterations--) {
printf("Angle: %2.1fdeg, Collision At: (%f, %f)\n", radian*(180.0/M_PI), dx,dy);
dx = targetPlayer.XCoordinate - myPlayer.XCoordinate +
(targetPlayer.XSpeed - myPlayer.XSpeed)*ImpactTime;
dy = targetPlayer.YCoordinate - myPlayer.YCoordinate +
(targetPlayer.YSpeed - myPlayer.YSpeed)*ImpactTime;
targetDistance = sqrt(dx*dx+dy*dy);
ImpactTime = targetDistance/myPlayer.BulletSpeed;

if (cur_error <= max_error) break;
}

• This is the first thing I thought of.. If my target travels faster then me.. then my speed will become 0 and it will be like I am not moving but what If I travel faster then my target? it will fail then. – SSpoke Jan 7 '14 at 22:28
• heh why would it fail? if you are moving faster than your target, that's the same as if your target is moving away from you, hence the negative result. – MickLH Jan 8 '14 at 1:08
• – SSpoke Jan 11 '14 at 3:16
Doubt I need to take into account that 10 milliseconds per game update, since when I don't move I never use 10 milliseconds and it works perfect.


I think that's where you're mistaken.

The fact is you say you do still miss 1% of the time when not moving. This miss rate results from a combination of the incident angle, distance, speed of shot relative to the speed of target, and size of shot relative to size of target -- remember that you are working only with points (centroids) and lines for trajectories, so a larger profile relative to the velocities for each object means a greater chance to hit. Catapulting a car quickly at a slow moving bus is more likely to hit, than catapulting a tennis ball at the same speed, at a faster-moving bus, due to the reduced profile of the tennis ball and the increased speed of the target.

In other words, a lot of the time, the combination of these factors will save you from misses, but not always. Reduce the sizes of shot and target, and make the shot angle perpendicular to the motion of the target, and you will start to see consistent misses. you should always be taking into account your 10ms lead time in your calculations. Your 1% miss rate under ideal conditions is likely a result of your not doing this sort of extrapolation.

You should find that if you do calculate one frame ahead as the target position, your hit ratio for moving target and gunner should increase to near to 100%. If you further use the 2 radii of the objects (or at least radii of their bounding circles) then you should experience a 0% miss rate, provided they experience linear velocities. If non-linear, rather more fluffy calculus will be required.

• Either way my math for both moving targets is completely off thats for sure, atleast can you tell me how I should fix that?. I just find those 10 milliseconds to be like dust anyways and I would have a hard time synchronization with those 10 milliseconds. I run this method outside the game loop in a different thread with also 10 millisecond sleep time (I guess this evens it up). which means I run it at slower then those 10 milliseconds the values update. Either way if the target drifts it actually is 100%, I mean overall it's not 100% since targets can change x,y speed at anytime in those 10ms – SSpoke Dec 31 '13 at 22:54
• Argh. You see, that's going to be a big problem. You should always, always have access to your actual time deltas in your main update loops, but most especially for physics. You really can't do accurate physics without that, all major game engines do so. All I can suggest outside of this is that your lead time had better be as accurate as possible. Then you simply need to multiply your velocity by the 0.01 seconds to get the additional offset, and include leeway for radii - do both of these for both objects, shot and target. You should still see some improvement, then. – Engineer Dec 31 '13 at 22:56
• Ya subtract a millisecond haha, I'll make that a adjustable parameter for experimenting. Either way both targets moving is completely wrong, I found my exact same question but I still don't understand it how to implement with my variables. gamedev.stackexchange.com/questions/28481/… – SSpoke Dec 31 '13 at 23:01

Change your bullet speed with bullet velocity (make it a vector value and not a scalar) and for each frame calculate its relative x,y movement. Take into account the fact that it's initial velocity is the sum of its velocity plus the player's velocity. Using vector math will give you 100% accuracy under any conditions.

• I don't understand what you mean make bullet speed into a vector? I can't figure out the bullet's X,Y speeds but I know it's actual speed..that's the paradox here, I don't know which direction it's traveling because it's not making any directions it's the player's angular heading that makes the direction. It's so complicated I have no idea what to do. – SSpoke Jan 6 '14 at 10:52
• I know the bullet speed shouldn't just be applied to the X,Y speeds of the player because that would mean it's going into a top right corner in a 2d plotting coordinate system where both x,y values are positive and it shouldn't travel in any direction at all.. it should do something to the target's distance that's for sure but it never takes into account my own speeds. Thats the whole problem I can't relate my own x,y speeds to change in relation to the bullet speed. It sounds simple that the bullet speed should just increase the x,y but it has to just increase a certain angle. Hard to explain – SSpoke Jan 6 '14 at 10:56
• By theory I believe the X,Y speeds should just change in some kind of percentage based on the bullet speed say if a Y coordinate is a negative value.. it should just increase to a bigger negative value not start turning slowly into a positive. I don't know what this math is called but it sounds similar to function ABS() but that won't help out.. How do I ignore if it's a positive or a negative and still keep it expanding in whatever direction it was going by the bullet speed. I'm guessing I'd have to loop check if a number is negative or positive then accordingly keep it in that path by BSpd – SSpoke Jan 6 '14 at 11:00
• How do I give a bullet that just has magnitude a direction? I know I could give it a direction which is the same as my own direction but what will that solve if anything. – SSpoke Jan 6 '14 at 11:11
• Using the angle of the shot you can easily convert bullet speed to bullet velocity (elementary high school trigonometry). The speed is actually the length of the hypotenuse of a triangle with x,y the vector coordinates we are looking for. So you end up with relative "speed" in each direction.depending on how you define the shooting angle x=speedcos(angle) or x=speedsin(angle) and y being the same in revers order. – Gus Jan 7 '14 at 6:24