Yesterday I was working on my OpenGL SDL project (aka "Super Trubo Ultra Hyper Hoover Tank Racer Ichi Ban" thanks to Ted), and wanted to calculate the trajectory of a bullet shot from the tank so that I could draw a crosshair at the end of a dashed line coming from the tank to aid with aiming.
The data that I had designed in the tank class related for this was the gun rotation angle, the gun tilt angle, and the power of the shot (starting velocity of the bullet), which I figured should also be enough to calculate the trajectory and thereby projected impact location of the bullet.
If you start with by using gun rotation angle (seen from top down) for the initial rotation of the world (what opengl does), then the rest of the problem becomes a two dimensional problem where the X axis is the direction along the shot, and the Y axis is the Z axis of the 3d world.
When drawing out this two dimensional problem I realized that I was drawing a quadratic equation, where the quadratic term was negative (the ends point down), something along the lines of
c + bx - ax^2 . I did some quick google-ing for a graph plotter and found
fooplot.com, which came in really handy.
|
Basic quadratic curve: 3x - 0.5x^2 (fooplot.com) |
I figured if I could relate the power of the shot (henceforth referenced as pow), and the tilt of the gun to the
a,
b, and
c of the quadratic equation I would be able to quickly calculate the impact point of the bullet, and draw my crosshair.
It was soon obvious that the
c variable only raised the graph up our down, and thus could be related to the current height the tank was hovering at. Changing the
b variable seemed to change the initial angle of the graph at the zero intersection (when keeping
c set to zero), but also thereby influenced the total distance the bullet would travel, which would relate to my pow variable. The a variable seemed to be mostly related to the pow, in that the smaller it got, the higher and further the graph would go.
After messing around with different values in fooplot, I found that the distance between the zero intersections (which could also be seen as the distance that the bullet would travel) was
a / b, while the max height of the graph was
(0.25b^2) / a . I have no algebraic proof, just the obvious relationships I found when messing with different input values.
|
equations for distance between intersections, and for max height |
Next I focused on relating the tilt of the gun to the angle found at the zero intersection (where the tank would be). Since the first derivative of a quadratic equation gives the rate of change at any point, it can be used to find the angle. The derivative of
c + bx - ax^2 is
b - 2ax, setting
x to zero for the tank location gives us that the rate of change at zero is
b.
The rate of change is the amount of change in y there is for every change in x, based on which we can draw the following triangle:
|
rate of change, for every 1 amount of x, we get b amount of y |
Where alpha in this triangle represents the tilt angle of the gun. And since tan(alpha) = opposite / adjacent, which in our case makes
tan(alpha) = b / 1 in other words, we get b based on the tilt angle:
b = tan(alpha).
The only thing left to calculate is
a... After drawing things out again, I realized that
a is basically the force of gravity, if it wasn't for it pulling the bullet downwards we would have the graph
c + bx which is just a straight line. So I decided to make gravity a force that pulls downwards 1 unit over time.
|
red: (4/3)x blue: (4/3)x - (1/9)x^2 |
But how does this relate to my variable pow? What is pow? It is the exit velocity of the bullet from the gun muzzle, and
velocity = distance / time. We could say that if in the above (red line) graph
pow = 5, the bullet would travel a distance of
5 in a single time frame, which would give the change in
x = 3 and the change in
y = 4 over that time frame (red line, without gravity).
But if we add in gravity (the blue line), we see that the bullet really ends up one unit lower, in other words with gravity
gx = 3, and
gy = 3 instead of the
4 we had for
y before. This made me realize that I could now solve for
a, since I had values for everything else.
I plugged in the numbers for the blue line into my formula
c + bx - ax^2, where:
c = 0 (no elevation)
b = 4/3 (based on the angle needed for my 3,4,5 triangle)
x = 3 (again based on my 3,4,5 triangle)
y = 3 (based on my 3,4,5 triangle, taking 4 - 1 for gravity)
solving for a:
3 = 0 + (3/4)3 - a3^2
3 = 4 - a9
a = -1/9
That was nice, but what did that say about
a in general? Repeating the same steps, but now with variables gave me:
y = c + bx - ax^2
a = (c + bx - y) / x^2
And so now, based on any given tank elevation, gun tilt angle, and pow (muzzle exit velocity), I'm able to create a quadratic equation. And using that equation, if I solve for zero using the quadratic formula, I can quickly find the distance to the expected bullet impact.
|
red crosshair totally working next to green velocity arrow |
It was totally cool, and I totally coded it into my little hover tank racer game, and then I realized that if I wanted to do things properly I would have to add the tanks' velocity onto the bullet's velocity for a proper real world trajectory... Which would make this whole quadratic equation business a whole lot harder, and I would be totally much better off doing the entire calculation with vector logic.
So yeah, I probably won't be using all this stuff I just figured out, but I had enough fun figuring it out that I didn't just want to throw it away, and instead figured I would archive it here, who knows maybe it will come in handy later? Or perhaps someone doing a search on the internets will stumble upon it and get something useful out of it.
During the process of figuring things out I had the thought several times that perhaps I should just try to google things, or read my essential mathematics for games book. But then I didn't since figuring it out was
so much fun :D
An interesting side note, writing this all up with graphics and everything actually took about as much time as it took me to figure everything out (didn't think writing would take this long).