Zelda, Mario and Donkey Kong fighting in Super Mario Smash Brothers

Solving Ballistic Trajectories

June 1, 2016

A common problem in video games is to calculate the angle to launch a projectile to hit a target. It’s so common I’ve written code to solve it on literally every game I’ve ever worked on.

Each time this problem comes up I tend to grab a pen and pad to re-solve it from scratch. I’m tired of doing that. To save future-self some time I’m going to put the solution on the internet. I’m also going to share a twist that I often prefer for design purposes.

TL;DR!

Want to skip the words and see the final result? Fine. I don’t blame you. Even if it makes me a little sad.

Equations of Motion

The problem always starts the same. Given a launcher and a target, at what angle must the projectile launch to hit the target?

There are four basic equations of motion. Today we’ll only be using one of them.

Equations of Notion

In plain English, the final position EQUALS initial position PLUS velocity times time PLUS one-half acceleration times time-squared. This simple equation, a little algebra, and a few trigonometric identities is all we need.

Refresh

Here’s a quick refresher before we get started.

Triangle Identities

Given a projectile with fixed speed S and launch angle θ (theta) we can compute the x and y components of velocity. Or if we have S and can otherwise determine y then we can solve for θ and x.

We’ll be using some Algebra.

Algebra

We’ll be making heavy use of the quadratic formula.

Quadratic forumla

Range

For video games we probably want to know the maximum range of a projectile. AI needs to know how close to move. Players need clear visual indicators showing danger zones.

There is a very simple equation for maximum range on a flat surface. But we’re going to jump off the deep end and start with the generalized form.

Given a projectile with fixed speed (S) and gravity (G) what is it’s max range?

Trajectory Image More equations
  1. Substitute known variables (y0, S, G) into our basic equation of motion.
  2. Apply quadratic formula. Ignore smaller term.
  3. Plug t back into x = S*cos θ*t and simplify.

Demo

For testing and to provide visualizations I created a Unity demo. It involves teapots shooting teapots. Pew pew!

Demo: WebGL Unity Demo

The demo has a handful of sliders. Here we see the range indicator for a teapot turret. As speed goes up range goes up. As gravity goes up range goes down. Pretty simple.

Firing Angle to Hit Stationary Target

Now the fun part.

Given a projectile with fixed speed (S) and gravity (G) at what angle should it be fired to hit a stationary target?

Math

Phew. We have two equations and two unknowns. Let’s break it down.

  1. First equation, two unknowns (t, θ)
  2. Second equation, two unknowns (t, θ)
  3. Solve (1) for t
  4. Plug (3) into (2)
  5. Trig substitution: sin θ/cosθ = tanθ
  6. Trig substitution: 1/(cos θ)^2 = 1 + (tan θ)^2
  7. Expand and rearrange
  8. Quadratic formula
  9. Multiply top/bottom by -S^2/x. Move S^4/x^2 into root
  10. Apply arctan to each side

Tada! This results in two angles. One low and one high. Here’s what it looks like in practice.

Visual Imperfection

Take a look at the gif above. When the teapot first starts shooting it looks pretty good. The high arc looks nice and pretty. The low arc feels crisp and efficient.

When range increases it doesn’t look so great. The low arc is almost flat. The high arc is comically high. This is the problem with a fixed speed projectile. It only looks good when the target is at the outskirts of its range.

What if there were a better way?

Lateral Speed

I often prefer to define projectile speed laterally. Only on the ground plane. I then explicitly define arc height. Which means vertical velocity and gravity become variable.

This has several advantages. First, it always looks good!

Second, it’s more intuitive for design. Designers don’t care about absolute speed. They care that a turret has a range of 20 meters and projectiles take 1 second to travel that distance. They shouldn’t need a graphing calculator to change balance numbers. Nor should artistic tweaks affect gameplay mechanics.

Third, it’s easier to hit a moving target. We’ll cover this in more detail in a bit.

Here’s what it looks like.

Solving with Lateral Speed

Given a projectile with lateral speed (S) and peak height (y_peak) what is velocity, gravity to hit a stationary target?

Equations
  1. Basic equation of motion
  2. Solve (1) for 2
  3. Define y_peak (user constant) to occur at (1/2)t
  4. Define y_end (target height) to occur at t
  5. Magic!
  6. More magic!
  7. Firing vector is (S, v.y) with gravitational acceleration g

Presto! Hey, wait a second. Magic? That’s cheating! Yes, but for a reason.

Steps (3) and (4) is another two equations with two unknowns. I’m lazy and don’t want to write it out. Plus I’d screw up and flip a sign. So I let a computer solve it for me.

More specifically, I used Wolfram Alpha. I recommend everyone have Wolfram in their toolbox. It’s quite handy.

Wolfram Alpha Solution

If a+c == 2b then y0, y_peak, and y_end are collinear. Which means you’re firing in a straight line.

Lateral Speed with Moving Target

At this point we have two different trajectory solutions. But enemies do not tend to stay in place. They move around. We need to solve the trajectory to hit a moving target.

This is where lateral speed shines. By defining speed on the ground plane it’s super easy to solve for a moving target.

Equations
  1. Where X is the target position and V is target velocity
  2. Square both sides.
  3. Re-arrange into quadratic
  4. Apply quadratic formula

For steps 5 through 9 refer to the previous section.

It makes me giggle with glee. Pew pew pew!

Fixed Speed with Moving Target

What if we wanted to hit a moving target with a fixed speed projectile? Oh boy. This is a can of worms! You don’t even know.

I’ve never actually shipped this in my career. Generally speaking games don’t want pinpoint artillery. It’s not fun! Instead you ballpark the future position and aim at a random point nearby. When players think of artillery they think of dumb shells raining around. Not perfect, laser guided death.

Writing this blog post I found the solution to a fixed speed projectile and moving target isn’t readily found on the internet. I’ll caveat this by saying you probably don’t want to do this in your game. But I spent a lot of time working this out. And damnit I don’t want that time to be for naught!

Quartics

The reason you don’t want to do this is quartics. The answer fundamentally involves a quartic.

Polynomials

Quadratics have an easy, elegant solution through the quadratic formula. Cubics are solvable a few different ways. Quartics are a bitch.

Solving quartics is well beyond the scope of this article. To be honest it’s beyond the scope of my mathematics ability. Fortunately for us, Graphics Gems I from 1990 has code for solving quartics. It’s available here. I used this code for my demo. I can not speak to it’s accuracy or numerical stability. Proceed with extreme caution.

Method One

Alright then. Let’s solve it. What is the angle to fire a projectile with fixed speed at a moving target? This method comes from a 2007 blog post by James McNeill. With reinforcement Ryan Juckett.

Polynomials
  1. Where P is target position and V is target velocity
  2. Square both sides
  3. Re-arrange terms
  4. Calculate quartic coefficients and plug into SolveQuartic
  5. Use t to calculate target position then calculate trajectory to stationary point.

This works. The heavy lifting is in SolveQuartic. We then use the stationary target solver from earlier in the post.

Method Two

Before discovering method one I derived the solution a different way. It involves way, way more steps. But I find the end result more elegant. Plus I used like 8 pages of papers and I don’t want those trees to have sacrificed themselves in vain.

Polynomials

Holy crap. Thirty two steps!? It’s worse than it looks.

The code is quite short. There are more lines devoted to variable declaration than actual math! Aside from SolveQuartic of course.

Polynomials

Warning

Code written for this test has not been battle tested. Nor has this post been peer reviewed. There are probably a handful typos, errors, and mishandled cases. If you find such a mistake please let me know. Discretely so no one knows my shame. 😁

In the meantime, treat this not as a finished solution but a solid starting point.

Creation Tools

I used a handful of tools in the creation of this post. Several of which were new to me.

LaTeX syntax is awful. Hideous and hard to learn. All LaTeX formulas can be found here. Here’s an example.

Polynomials

Conclusion

That just about does it. I spent way more time on this post than I expected. I solved a case I’d never solved before and I learned a few new tools. A worthwhile endeavor.

Nothing in this post is new or original. I tried to explain things thoroughly without being overly verbose. I feel pretty good having complete descriptions all in one place. Hopefully this is helpful to a few folks out there.

Thanks for reading.