OK, let me preface this by saying i am not a physics student, nor have i ever been. I am a software engineer working on a development degree. So this is homework but the assignment was just to create an app, i chose to do this app and the teacher said he couldn't assist because this is a development class not a physics class.

This is what i have done:

First, I made an app to calculate the angle required for a projectile to hit a given target. (using bullets as the projectile). The first attempt was successful however the only force acting on the bullet wa gravity and i was able to calculate the correct angle.

NOW, I am attempting to do the same with regards to adjusting the shooting angle to hit a required target WITH air resistance. I have already taken the initial velocity and broken it into the x & y components, calculated a cross sectional area, have the weight of the bullet in grains, and the drag coefficient.

How do i calculate the angle required to hit a target?

lets assume the following: i am firing a bullet from (0,0) to hit a target 1000 yards away, my bullet weighs 170 grains, ballisticCoefficient of the bullet is .25 .

so i have this

muzzleVelocity = 2000 fps

velocityX = muzzleVelocity * cos(targetAngle)

velocityY = muzzleVelocity * sin(targetAngle)

airDensity = calculate elsewhere 1.168783

crossSectionalArea = calculate by using the bullet diameter ((1/2 Diameter)^2 * PI) = area of a circle

Drag = (airDensity * ballisticCoefficient * crossSectionalArea)

AccelrationX = -(drag/grain)*muzzleVelocity * velocityX)

AccelrationY = -g -(drag/grain)*muzzleVelocity * velocityX)

  1. What do i do now?

  2. Do i need to convert the crossSectionalArea to the same unit of measurement as the velocity?

The things i know are total velocity, bullet weight, bullet diameter, air density, distance and angle to the target. How can i determine the angle required to hit a target?

I am loosely following here http://wps.aw.com/wps/media/objects/877/898586/topics/topic01.pdf

however i am a computer programmer and this looks greek to me.

Thanks Jeff



float velocityX = 0;

float velocityY = 0;

float accellerationX = 0;

float accellerationY = 0;

float drag = 0;

float timeInterval = .001;

caliber = [self.caliberTextField.text floatValue];

ballisticCoefficient = [self.ballisticCoefficientTextField.text floatValue];

muzzleVelocity = [self.muzzleVelocityTextField.text floatValue];

grain = [self.bulletGrainTextField.text floatValue];

velocityX = muzzleVelocity * (cosf(targetAngle / 180 * M_PI));

velocityY = muzzleVelocity * (sinf(targetAngle / 180 * M_PI));

if(self.metricSwitch.on == YES){

    crossSectionArea = pow(((caliber * 0.00109361)/2),2)* M_PI;


    crossSectionArea = pow(((caliber / 36)/2),2)* M_PI; //pow(((caliber / 36)/2),2)* M_PI;


NSLog([NSString stringWithFormat:@"airdensity %f, BC %f, cross %f", airDensity, ballisticCoefficient, crossSectionArea]);

drag = (airDensity * ballisticCoefficient * crossSectionArea);

NSLog([NSString stringWithFormat:@"drag %f", drag]);

accellerationX = -(drag/grain)*muzzleVelocity*velocityX;

accellerationY = -g - (drag/grain)*muzzleVelocity*velocityY;

NSLog([NSString stringWithFormat:@"X %f, Y %f", accellerationX, accellerationY]);


for (x=0; x<3; x+=.001) {

    accellerationX = -(drag/grain)*muzzleVelocity*velocityX;

    accellerationY = -g - (drag/grain)*muzzleVelocity*velocityY;

    float nextx = (velocityX + );



EDIT FOR CLARIFICATION So when you said "You need to use the current velocity at any step of the calculation", i was beginning to do that (in a small loop for test purposes).

I was going to test output using just three seconds in my for loop (x = seconds)

for (x=0; x<3; x+=.001) {

accellerationX = -(drag/grain)*muzzleVelocity*velocityX;

accellerationY = -g - (drag/grain)*muzzleVelocity*velocityY;
float nextx = (velocityX + );


I was planning on solving the NEW x,y locations based off of the negative acceleration in both the X,Y plane and then adjust the x & y velocity each iteration (every .001 seconds), and thats when it dawned on me that since I am down to thousandths of seconds and thousandths of a degree... This could be a VERY large computational process.

Suffice to say i could probably do split halves to narrow it down between whole degrees and then go from there with the other calculation methods. You have provided great info in the links... i had no clue what is what called. I just know what i needed to do and it looks like i was correct that there is no hard fast formula to plug in. I will finish reading the links provided and see if i can grasp a better understanding of either of the methods.

to recap: I will try (0,5,10,15,....90) to see what range the angle should fall between.

Then use the formula to further narrow it down to my desired precision level by calculating the next x,y by adjusting the position and current velocities.

an after thought, i suppose i could increase my time interval as well.


3 Answers 3


A couple things, first you are not discussing air resistance correctly. The drag depends on the current velocity, which is a dynamical quantity, not just on the muzzle velocity. You need to use the current velocity at any step of the calculation.

Second, in broad terms, you can think of the problem you face as one of root finding. You have some function $d(\theta)$ that returns the distance travelled as function of theta, and you want to know what argument of $\theta$ will make it equal some special value: $d^*$. You can think of this as finding the root (the place where it crosses zero) of the function $$ f(\theta) = d(\theta) - d^* $$

And there exist efficient algorithms for doing this without having to check every single value of $\theta$. For this problem in particular, I would recommend the secant method, which is an iterative procedure to give you improved guesses. In this case, it would give you a new guess based on your previous two guesses as: $$ \theta_n = \frac{ \theta_{n-2} d(\theta_{n-1}) - \theta_{n-1} d(\theta_{n-2}) + d^* ( \theta_{n-1} - \theta_{n-2} ) }{ d(\theta_{n-1}) - d(\theta_{n-2}) } $$ Where $\theta_{n-1}$ is the previous guess at the angle, $\theta_{n-2}$ is the guess before that, and $d(\theta_{n-1})$ and $d(\theta_{n-2})$ were the calculated distances for those angles. You do this iteratively until you've converged, meaning your guess doesn't change much $$ | \theta_n - \theta_{n-1} | < \epsilon $$ with $\epsilon$ some small number you choose that governs your precision, $10^{-5}$ say.

Now you just have to write a routine $d(\theta)$ that calculates the distance a bullet travels for a given angle and you can find the right angle for any distance in short order.

To help with that, I suggest you use leapfrog integration, or if you prefer, see this se/gamedev answer geared towards programmers.

  • $\begingroup$ Changed from an edit to another comment $\endgroup$
    – Jeff Brown
    Jul 25, 2014 at 0:48
  • $\begingroup$ @JeffBrown What? $\endgroup$
    – alemi
    Jul 25, 2014 at 0:53
  • $\begingroup$ i was typing a comment but it wouldn't fit... so i edited the original with a response see section "EDIT FOR CLARIFICATION" $\endgroup$
    – Jeff Brown
    Jul 25, 2014 at 1:05

The distance is a function of the angle. I am pretty sure you won't be able to obtain the inverse function analytically, not taking into account air resistance, so you should solve the relevant equation numerically, using one of the well-known methods, such as dichotomy or the secant method.


OK, i have since edited this, but the results are still off. What am i missing? My first step is just to be able to calculate the x,y values for the given angle.

I have omitted irrelevant methods in code, i just need someone to assist with the PHYSICS portion. i a just missing something. CODE BEGIN const float g = 32.2; // gravity 9.8m/sec^2 or 32.2ft/sec^2

float ay = 0; // acceleration for y

float ax = 0; // acceleration for x

float Vt = 0; // terminal Velocity

float W = 0; // Weight

float D = 0; // Drag

float m = 0; // Mass

float Cd = 0; // Coefficient of Drag

float r = 0; // gas density

float A = 0; // cross sectional Area

float v = 0; // velocity for y

float u = 0; // velocity for x

float Vo = 0; // initial Vertical Velocity

float Uo = 0; // initial Horizontal Velocity

float t = 0; // time

float airTime = 0; // airTime

float caliber = 0; // caliber/diameter of bullet

float grain = 0; // mass of bullet

float peakTime = 0;

float muzzleVelocity = 0;

float airTemp = 0;

float barometricPressue = 0;

float x,y = 0;

float yMax = 0;

float targetAngle = 0;

float trueDistance = 0;

float horizontalDistance = 0;

float verticalDistance = 0;

float rifleZeroDistance = 0;


// Rifle Zero Distance

rifleZeroDistance = [self.rifleZeroDistanceTextField.text floatValue];

// Ballistics Coefficient

Cd = [self.ballisticCoefficientTextField.text floatValue];

// Cartridge Caliber

caliber = [self.caliberTextField.text floatValue];

// Total Muzzle Velocity

muzzleVelocity = [self.muzzleVelocityTextField.text floatValue];

// Bullet Mass

grain = [self.bulletGrainTextField.text floatValue];

// Convert grains to grams

m = grain/15.432;

// Weight

W = m * g;

// Cross sectional Area (Metric or English Conversion to yards

if(self.metricSwitch.on == YES){

    // Area in MM converted to yards

    A = M_PI * ((.5 * caliber * 0.00109361)*(.5 * caliber * 0.00109361));


    // Area in inches converted to yards

    A = M_PI * ((.5 * caliber) * (.5 * caliber))/36;


// Terminal Velocity

Vt = sqrt((2 * m * g) / (Cd * r * A));

// Drag

D = .5 * Cd * r * A * (Vt * Vt);

// Initial Velocity

Vo = muzzleVelocity * (sinf(targetAngle / 180 * M_PI));

Uo = muzzleVelocity * (cosf(targetAngle / 180 * M_PI));

// Local Velocity (initially the same as Vo/Uo)

v = Vo;

u = Uo;

// Accelleration

ay = -g * (1 + (v*v) / (Vt * Vt));

ax =  - (Cd * r * A * (u * u)) / (2 * m);

// Velocity at time

//v = (Vo - Vt * tan(g * t / Vt)) / (Vt + Vo * tan (g * t / Vt));

// Peak Y time

peakTime = (Vt / g) * atan(Vo/Vt);

// Y Value at given Time

//y = ((Vt* Vt) / (2 * g)) * log(((Vo * Vo) + (Vt* Vt))/((v * v) + (Vt* Vt)));

// Y Max Value

yMax = ((Vt* Vt) / (2 * g)) * log(((Vo * Vo) + (Vt* Vt))/(Vt* Vt));

// AirTime

airTime = (Vt * -atan(v/Vt))/-g;



// When i calulate this attempting to get velocity &

// Y values for Time, The velocity is WAY off and the yVal Never Changes

for (t = .0; t < airTime; t+= .01) {

    // Local Velocity for Y

    v = (Vo - Vt * tan(g * t / Vt)) / (Vt + Vo * tan (g * t / Vt));

    // Local velocity for X

    u = (Vt * Vt) * Uo / ((Vt * Vt) + g * Uo * t);

    // y Coordinate for time = t

    y = ((Vt * Vt) / (2 * g)) * log(((Vo * Vo) + (Vt * Vt))/((v * v) + (Vt * Vt)));

    // x Coordinate for time = t

    x = ((Vt * Vt) / g) * log((Vt * Vt) + g * Uo * t) / (Vt * Vt);

    // ?????? UPDATE Vo/Uo so next iteration will have different updated velocities

    Vo =v;

    Uo = u;

    NSLog([NSString stringWithFormat:@"\n Time:%1.2f, \n velocity X: %1.3f\n velocity Y: %1.3f\n Pair: (%1.3f,%1.3f)",t, v, x, y]);


NSLog([NSString stringWithFormat:@"\n\n\n\n Vo=%f\n Mass = %f\n Weight = %f\n Cross-sectional Area = %f\n Terminal Velocity = %f\n Drag = %f\n acceleration X = %f\n accelrtaion Y %f\n Time = %f\n peakTime = %f\n yMax = %f\n", Vo, m, W, A, Vt, D, ax, ay, airTime, peakTime, yMax]);


// Calculate angle required to hit target at given location with drag by using secant/dichotomy/split half method

// Use triangle rules and distances from user to determine the difference in Y values of the two triangles

// The Y difference will be the amount of hold over needed to hit the target

// In addition to displaying Holdover, determine the "number of clicks" of

// adjustment based on MIl dot/ MOA at target distance

// User will then be able to "holdover" or adjust with clicks

[self.tabBarController setSelectedIndex:1];



Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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