1
\$\begingroup\$

In my game I want skeletons to occasionally lob bones at the player. The player can be anywhere in relation to the skeleton (above or below, to the left or right), and I want the skeletons to throw a bone such that it lands on the player (or its parabolic arc intercepts them while rising, if the player is above the skeleton).

Given an arbitrary starting position, an arbitrary target point, and an arbitrary launch angle, how can I calculate the initial velocity of a ballistic projectile (assuming no air resistance) such that its parabolic trajectory intercepts the target point?

I know there are a number of similar questions on this site, but none of them appear to have this particular set of requirements:

Calculating initial velocities given trajectory parabola requires a known/fixed apex height.

Calculating velocity needed to hit target in parabolic arc and Throw object towards predefined place? assume a known/fixed travel time.

I want to have a fixed launch angle, initial position, and final position, and from those determine the initial velocity.

The Wikipedia article Trajectory of a projectile comes close, but I have no idea how to solve that for velocity.

Reference

Reference Image

In computer coordinates, the Y axis is inverted from Cartesian coordinates. The accepted formula operates independently of this, but it's unintuitive to deal with. This means that gravity will be a positive number, while being above the projectile will result in a negative displacement.

This also means that the fixed angle you choose will be the negative of what the habitual version would suggest.

As a final note, I adjusted for the absolute value of Vx by performing this manipulation before calculating Vy:

if sign(x_velocity) != sign(delta_vector.x):
    x_velocity = -1 * x_velocity
var y_velocity = x_velocity * tan(angle)

Full pseudocode reference:

static func get_velocity_of_arc_intercept(initial_position, target_position, angle):
    var delta_vector = target_position - initial_position
    var x_velocity = sqrt((gravity * delta_vector.x * delta_vector.x) / (2 * (delta_vector.y - (tan(angle) * delta_vector.x))))
    # Adjust for lost sign.
    if sign(x_velocity) != sign(delta_vector.x):
        x_velocity = -1 * x_velocity
    var y_velocity = x_velocity * tan(angle)
    return Vector2(x_velocity, y_velocity)
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

First note that the initial velocity V at angle theta (from the horizontal, without loss of generality) has X and Y components Vx and Vy given by:

Vx = V cos(theta)
Vy = V sin(Theta)

Then by referencing the equations in my answer here, one readily obtains that at the time t of intersection:

Dy = Vy t  + g (t^2) / 2
Dx = Vx t

where Dx and Dy are the relative displacement of the target from the thrower.

Eliminating t in the first by substitution of the second gives

Dy = Vy (Dx/Vx) + g ( ((Dx/Vx) ^ 2) / 2

and then by rearranging

(Vx ^ 2) Dy = Vy Vx Dx + g (Dx ^ 2) / 2

But Vy == Vx tan(theta) from the problem statement, so

(Vx ^ 2) Dy = (Vx ^ 2) tan(theta) Dx + g (Dx ^ 2) / 2

or

(Vx ^ 2) (Dy - tan(theta) Dx) = g (Dx ^ 2) / 2

which finally becomes

Vx = sqrt( g (Dx ^ 2) / ( 2 (Dy - tan(theta) Dx) ) )

and then |V| = |Vx| / cos(theta)

\$\endgroup\$
9
  • \$\begingroup\$ I'm getting sqrt(negative_number) for Vx. Does this only work in Quadrant I, or did I botch my implementation somehow? \$\endgroup\$ Sep 27, 2016 at 23:56
  • \$\begingroup\$ I'm plugging in some example numbers which seem reasonable and getting imaginary numbers back from the square root. My intuition suggests that as long as the player is below the skeleton and the fixed angle is in the correct direction (Quadrant II for left or Quadrant I for right), there should always be some velocity which will intersect at that angle. Is that an incorrect assumption? \$\endgroup\$ Sep 28, 2016 at 0:34
  • \$\begingroup\$ @HammerBro.: Make sure that you have consistent sign conventions with all quantities. Acceleration due to gravity must be directed downwards, sign convention for vertical and horizontal must be consistent between displacement and velocity, etc. Getting signs right is the bug-a-boo of high school physics students. \$\endgroup\$ Sep 28, 2016 at 1:02
  • \$\begingroup\$ @HammerBro.: Only if the target remains in the quadrant long enough for the projectile to drop, starting with zero velocity, to the target. \$\endgroup\$ Sep 28, 2016 at 2:56
  • 1
    \$\begingroup\$ Turns out it was a dumb error on my part; the angle I chose for leftward-facing shots was actually a downward angle, not an upward angle, so of course it couldn't hit a target above it. (Which technically would've been in Quadrant III; still not used to translating into screen coordinates.) \$\endgroup\$ Sep 30, 2016 at 3:24

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .