# Projectile: initial velocity angle to hit coordinate.

While working on an aiming system for one of my games, I faced this problem: **“What should be the initial velocity angle for a projectile to hit given coordinate?”** I wanted the bullet to pass thru mouse position. This image illustrates the problem:

The projectile should hit coordinate marked with red cross. The launcher has fixed power and bullets have fixed mass, so in my scenario the initial velocity vector length will be constant (I will adjust it accordingly to get nice gameplay). The intuition says that I’ll end up with more than one trajectory. One will hit the coordinate after reaching maximum height and another will use the shortest parabolic path.

I tried to solve the problem by hand. It was clear that I need to start with basic trajectory equations for `x`

and `y`

movement and solve them for `theta`

angle:

Things quickly started to go wrong and even Wolfram wasn’t sure how to simplify. That was bad, but fortunately someone on the Wikipedia did remember the tricky trigonometric substitutions and wrote this:

It says that the angle of the initial velocity vector depends on:

`v`

– initial velocity (the length of velocity vector);`g`

– gravity value (given by positive number);`x`

,`y`

– coordinates of the point that we want to hit;

Cool! First, It says that there are two solutions: one for adding square root and one for subtracting it (like I said, I’ll get two trajectories). Second, square root’s argument must be equal or greater than zero. Third, there’s `x`

and `g`

in the denominator, so both have to be non-zero. For now I just assume that square root argument has to be valid to make the projectile reach `(x, y)`

coordinate. Gravity `g`

must be non-zero to even think of ballistic behavior. If the `x`

is zero, then the angle is straightforward: `π/2`

or `-π/2`

depending on `y`

sign.

I did small Flash application for testing this equation:

This demo uses Nape physic engine and works with Flash coordinates system, where `(0, 0)`

means top-left corner of the screen. But ProjectileUtils class is designed for “human” coordinate system, where `[0, 10]`

is the velocity for up movement. Pass the gravity as a positive number. Feel free to grab the source code from GitHub Projectile-Utils repository or just take a look at ProjectileUtils class:

package { /** * Projectile trajectory utils. * @author maciek grzybowski, 10.11.13 14:29 * */ public class ProjectileUtils { /** * Checks if projectile can hit (x, y) coordinate with initial velocity length under given gravity. * @param x * @param y * @param velocity initial velocity * @param gravity gravity value; should be greater than 0 * @return */ public static function canHitCoordinate(x:Number, y:Number, velocity:Number, gravity:Number):Boolean { return calculateDelta(x, y, velocity, gravity) >= 0; } /** * Calculates angle to hit given (x, y) coordinate with given velocity and gravity. * @param x * @param y * @param velocity initial velocity * @param gravity gravity value; should be greater than 0 * @return angle in radians */ public static function calculateAngle1ToHitCoordinate(x:Number, y:Number, velocity:Number, gravity:Number):Number { if (x == 0) return y > 0 ? -Math.PI * 0.5 : Math.PI * 0.5; var delta:Number = calculateDelta(x, y, velocity, gravity); var sqrtDelta:Number = Math.sqrt(delta); return Math.atan((velocity * velocity - sqrtDelta)/(gravity * x));; } /** * Calculates angle to hit given (x, y) coordinate with given velocity and gravity. * @param x * @param y * @param velocity initial velocity * @param gravity gravity value; should be greater than 0 * @return angle in radians */ public static function calculateAngle2ToHitCoordinate(x:Number, y:Number, velocity:Number, gravity:Number):Number { if (x == 0) return -Math.PI * 0.5; var delta:Number = calculateDelta(x, y, velocity, gravity); var sqrtDelta:Number = Math.sqrt(delta); return Math.atan((velocity * velocity + sqrtDelta)/(gravity * x)); } private static function calculateDelta(x:Number, y:Number, velocity:Number, gravity:Number):Number { return velocity * velocity * velocity * velocity - gravity * (gravity * x * x + 2 * y * velocity * velocity) } } }