function calculateFiringSolution(start: Vector, end: Vector, muzzleV: float, gravity: Vector) -> Vector: # Calculate the vector from the target back to the start delta: Vector = start - end # Calculate the real-valued a, b, c coefficients of a quadratic a = gravity.squareMagnitude() b = -4 * (dotProduct(gravity, delta) + muzzleV * muzzleV) c = 4 * delta.squareMagnitude() # Check for no real solutions b2minus4ac = b*b - 4*a*c if b2minus4ac < 0: return null # Find the candidate times time = sqrt((-b + sqrt(b2minus4ac)) / (2 * a)) time1 = sqrt((-b - sqrt(b2minus4ac)) / (2 * a)) # Determine the valid time to target if time < 0: if time1 < 0: return null else: ttt = time1 else: if time1 < 0: ttt = time else: ttt = min(time, time1) # Return the firing vector return (delta * 2 - gravity * (ttt * ttt)) / (2 * muzzleV * ttt)
Explanation
This is the closed-form ballistic solution for hitting a static target with constant gravity.
Steps:
Compute displacement (Note: the pseudocode has it backwards)
[
\Delta = end - start
]
Solve a quadratic in (t^2) derived from projectile motion.
The two solutions correspond to:
high arc
low arc
Pick the smallest positive time.
Plug that time into the velocity equation to compute the launch direction vector.
The final vector is the normalized firing direction scaled by muzzle velocity.