DEVBLOG #3: Ballistics
Tags: physics
Published: 2022-04-16 05:17:02

Here's a photo of my current ballistics solution, involving penetration & penetration refraction, elastic ricochets, air drag, terminal velocity (color = velocity):
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ykosqi6li4bb2pey6cpn.png)

Since almost all of the games I've worked on involved some sort of ballistics, being either projectiles such as bullets or aerodynamics for planes, I've put quite a lot of time into them. In this article I'll go over my process of creating the system I use today.

In a lot of games, such as Call of Duty (before MW19), your bullets were hit scanned: that means they form a ray that would immediately hit whatever you aimed at no matter how far away your target is. In a lot of other games (MW19, Battlefield), your bullets have velocity and are affected by gravity, just like in real life. Not only does the latter make the game feel more realistic, it also helps to balance weapons with larger maps.

However, just having velocity and gravity isn't enough (at least for me). In Battlefield, the damage rolls off based on distance. This helps force the combat to happen at closer ranges, and also mitigates people who are really good at the game from killing others across the map. It is also missing a key feature that's present in ballistics on the surface of the Earth in real life: aerodynamic drag. This will slow your projectile down based on the square of its velocity. ![https://www.grc.nasa.gov/WWW/k-12/airplane/drageq.html](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/59wkezym38bck8f5hfea.png)
 
The above image is the source of the equation I use, however it looks more complex than it is, since you can assume that Cd and the surface area for the projectile are constant (unless you want to simulate tumbling), and the air density can just be 1 (unless you want your game to take into account high altitudes). Great, so now I can just paste that into the game? Well, yes and no. Because I also have other things in place for the ballistics in my game: zeroing.

Arma 3 ACE mod does all of this for their ballistics. It models velocity, gravity, ballistic coefficients of projectiles, temperature, pressure, humidity, wind, altitude, air friction, barrel twist, Coriolis effect, and probably more. (https://github.com/acemod/ACE3/blob/master/extensions/advanced_ballistics/AdvancedBallistics.cpp) However this is overkill for what I wanted, which was simply just velocity, gravity, drag, and perhaps wind. The issue with the ACE implementation is that 

1. It has to iteratively estimate the zeroing for the projectiles and asymptotically arrive at the correct answer
2. It is a discrete solution, it depends upon its last position to calculate where it will be next at discrete time steps.

The most important one is #2. This is because a continuous solution is ideal, as you can easily find where a projectile will be at a given time with a single calculation instead of stepping through time intervals and calculating it over and over again. This makes it easier and faster to do things such as zeroing and trajectory prediction. It also makes it easier and faster for other clients to simulate a copy of your own client projectile, because they know exactly where your projectile will be at what time (When they hit obstacles, I simply reset their velocity / position on the other clients).

So, the first thing I did was look at the math that requires this, and also search the internet for solutions. As stated previously, the force of air friction on a projectile primarily relies on its velocity squared. In turn, it will slow down its velocity. This is messy, because you have a variable that's dependent upon itself. The first thing that came to mind was calculus 2, however I never took a class past calc 1 and I didn't want to bother learning it exclusively for this. So I looked into hacking it to get the desired results. Here are the requirements I made:

- I needed a solution where the velocity variable didn't rely on itself to slow itself down
- The solution must be easy to calculate
- The solution must asymptotically reach a terminal velocity which also means reaching 0 acceleration

So I did a bunch of thinking in my head and plotted it in desmos and I eventually came up with this equation:

drag = 1 / (t * d + 1)
where:
t = time
d = ballistic coefficient

All you have to do is multiply the projectile's position equation by this. A d of 0 is a vacuum, and a d of 0.5 would mean that the velocity cuts in half after 2 seconds. Since the drag is calculated off of a constantly increasing value (time) instead of a dynamically changing variable (velocity), it makes it much easier to calculate. At first I believed this would have unintended effects, since slowing the velocity based on time instead of velocity seems completely unrelated. However, I graphed it and it checked off all three requirements I had. (Short video of me changing d value here: https://i.gyazo.com/b26f41219a239d3a59fbe6083529dd78.mp4) As a side effect, I can also make the drag negative, which could be useful for accelerating projectiles such as rockets.

I took this equation and implemented into my game to exceptionally well results. It was extremely cheap to calculate, and made it very easy to balance weapons. It was incredibly easy to make sub-machine guns great at close quarters and unfeasible at long ranges. I also didn't have to come up with a system for bullet damage dropoff like what battlefield uses, as I could just directly use its current velocity to calculate damage. I also compared the trajectory to real life trajectories and found that it was fairly accurate. The only thing it doesn't model is the transition of a projectile from supersonic to transonic to subsonic as the amount of drag on the projectile will vary. Nonetheless it was accurate for a purely supersonic and also for a purely subsonic projectile.

However, next I have to solve problem #1: zeroing. Right now I've quickly put together an iterative solution for this that's quite accurate, however eventually I'll put time aside to properly solve it. I've also been working on implementing wind into it, because why not, and I've made some substantial progress with it. I didn't go over my ricochet or penetration system, but I suppose that can be for another article.