Example Lab Report

Simulation of Projectile Motion


In many games, there will be objects moving under free flight. If a game is to be perceived as realistic, these various projectiles must have movements that are realistic. When an object is launched with some velocity and allowed to fly freely, that is there's no thrust from a motor or wings or the like, its said to be in “ballistic” flight. Most objects in ballistic flight, experience only an acceleration due to gravity. This means that even in a 3D environment, the simulation of motion can be treated as a 2D problem by separating the motion into a vertical and horizontal component. If an object's size is large compared to its mass, or if the speed of the object is high, then wind resistance can be an important factor. Although including the effects of wind resistance does add complexity to a simulation, its inclusion can bring a much higher level of realism to a game or simulation.


The simulation of projectile motion can be treated as two separate 1D problems, one in the horizontal and one in the vertical direction. In this simulation, all quantities are measured in standard SI metric units so that positions are measured in meters, velocities in meters per second, accelerations in meters per second squared and time in seconds. All physical parameters are treated at single-precision floating point variables. Neglecting wind resistance, the only acceleration considered for the projectile is the vertical acceleration due to gravity taken as 9.8 m/s2 in the downward direction. The acceleration due to the effects of wind resistance is modeled by the following:

\begin{equation} a_{wind} = - c v \end{equation}

where $c$ is the “coefficient of wind resistance” measured in units of $1/s$ and $v$ is the velocity measured in $m/s$. Since we consider the acceleration as result of wind resistance to be linear with velocity, the above equation can be treated strictly as a scalar equation.

Motion from one timestep to the next is integrated using the Forward Euler Method. While this algorithm is not as precise as others, it is simpler to code and executes much faster. The primary artifact of the Forward Euler Method is that projectiles will tend to fly farther than they should, but if the timestep is kept small, this error can be kept to a minimum. With that in mind, the timestep used for the simulation is 0.04 s which corresponds to a frame rate of 25 fps. Including the effects of wind resistance, the velocities in the horizontal and vertical directions are modeled in the following way:

\begin{align} v_{x new} = v_{x old} - c \cdot v_{x old} dt \end{align}


\begin{align} v_{y new} = v_{y old} - c \cdot v_{y old} dt. \end{align}

Once the new velocities are known, the new positions can be calculated,

\begin{equation} x_{new} = x_{old} + v_{x old} dt \end{equation}


\begin{equation} y_{new} = y_{old} + v_{y old} dt \end{equation}

The initial position for the projectile is taken to be the origin (x=0, y=0), and the magnitude and direction for the initial velocity is supplied by the user with the direction being the angle above the horizontal measured in degrees. The user is also asked to supply a coefficient wind resistance, which is taken to be the same for both directions. After acquiring the initial data from the user, the angle for the initial velocity must be converted to radians so that it may be passed to the cosine and sine functions in the <cmath> library when determining the initial horizontal and vertical velocities,

\begin{align} v_x = v_i \cos \left( \theta \right) \end{align}


\begin{align} v_y = v_i \sin \left( \theta \right). \end{align}

Every timestep, the elapsed time and the position of the particle are displayed via a console window. The simulation terminates when the vertical position of the projectile is less than zero, indicating that the projectile has reached the ground. At the end of the simulation, the total elapsed time and the total horizontal distance are displayed.


Examining a couple of test situations will reveal the validity of the methodology described above. If there is no wind resistance, then the total range for a projectile launched over flat terrain is given by

\begin{align} \Delta x = \frac {v^2} {g} \sin \left( 2 \theta \right) \end{align}

This means that the maximum range for a given initial speed happens when the initial angle is 45 degrees, and that initial angles of 30 degrees and 60 degrees should yield the same range. Below is a table showing the range for a projectile launched at 20 m/s for a variety of angles.

Speed (m/s) Angle (degrees) Simulated Range (m) Analytical Range (m)
20 15 21.6 20.4
20 30 36.7 35.3
20 45 41.9 40.8
20 60 36.0 35.3
20 75 20.7 20.4

To evaluate the validity of simulations treatment of wind resistance, the maximum range should happen at an angle slightly less than 45 degrees, and at each angle the total range should be less than the corresponding range without wind resistance. The table below shows the results of the simulation using an initial velocity of 20 m/s as before, but with a coefficient of wind resistance of 0.2 1/s.

Speed (m/s) Angle (degrees) Simulated Range (m)
20 30 27.0
20 37.5 28.9
20 45 28.2
20 52.5 26.8
20 60 23.3


This numeric model for projectile motion functions quite well. Although there were deviations from the analytical solution, the errors were small, and in a game environment these small errors would not be a significant hindrance. If higher precision were needed, a smaller time-step could be used. The wind resistance model performed very well. There was no analytically derived data for comparison, but performance of the model matched the qualitative expectations and is sufficient for most game environments.


/    ProjectileMotion.cpp simulates the motion of a projectile fired
/    at a user-supplied angle and velocity over flat terrain.  The user
/    will also supply a value for the horizontal wind velocity and a
/    coefficient for wind resistance.  The particle's position is
/    displayed via the console after every timestep until the projectile
/    reaches the ground once again.
/    J. Douglas Patterson, Jan 2009
/    Johnson County Community College
#include <cmath>
#include <iostream>
using namespace std;
void main() {
    float t=0.0f;        // elapsed time for the simulation (s)
    float dt=0.04f;        // timestep corresponsing to 25 fps (s)
    float x=0.0f;        // horizontal position (m)
    float y=0.0f;        // vertical position (m)
    float g=9.8f;        // acceleration due to gravity (m/s^2)
    float cwind=0.0f;    // coefficient of wind resistance (1/s)
    float vx=0.0f;        // horizontal velocity (m/s)
    float vy=0.0f;        // vertical velocity (m/s)
    float vi=0.0f;        // inital speed (m/s)
    float theta=0.0f;    // intial elevation (degrees)
    cout<<"Enter the initial speed and angle in degrees: ";
    theta = theta * 0.0174533f;        //convert elevation to radians
    cout<<"Enter the coefficient of wind resistance: ";
    /* Determine velocity vector components */
    vx = vi * cosf(theta);            
    vy = vi * sinf(theta);
    /* Simulation loop.  Continue until projectile reaches the ground */
    while (y >= 0) {
        /* update the position */
        x += vx * dt;
        y += vy * dt;
        t += dt;
        /* update the velocity */
        vx += -cwind * vx * dt;
        vy += ((-cwind * vy) - g) * dt;
        cout<<"Time: "<<t<<" s, Position ("<<x<<", "<<y<<") m\n";
    cout<<"The projectile lands "<<x<<" m down range.\n";
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License