I'm trying to implement a turret in a game that compensate for bullet drop, I'm using the equations 1) and 2) from the next image to obtain the angle of the turret and time of flight.
But it doesn't work when the target have a higher altitude (assuming h is the difference in height) like in 3), and the angle is always positive, but I want the turret to aim downwards when it have a higher ground like in 4)
https://i.stack.imgur.com/Jkngw.png
g = gravitational acceleration in m/s^2
v0 = muzzle velocity in m/s
h = difference in height between muzzle and target in meters (will be negative if the target have a higher altitude)
d = projected distance between muzzle and target over the XZ plane in meters
[unknown] angle = angle of the turret in degrees (between -45º and 45º from the horizon)
[unknown] time = estimated time of impact in seconds
function ProjectileMotion(g, v0, h, d)
denom = sqrt(h * h + d * d)
coef = ((g * d * d) / (v0 * v0) - h) / denom
phase = atan(d / h)
angle = (pi - (acos(coef) + phase)) / 2
v0_y = v0 * sin(angle)
time = (v0_y + sqrt(v0_y * v0_y + 2 * g * h)) / g
return to_deg(angle), time
end
The question is: How can I get the angle (between -45º and 45º) and the time of flight, given:
g = 9.8 m/s^2,
v0 = 50 m/s,
delta_h = turret_height - target_height,
d = horizontal distance
?
EDIT: Finally found a solution.
I used the formula in this video that only works for angles between 45º and 90º, I subtracted 90º to that angle to get a value between 0º and 45º, then for the phase angle the height need to be positive.
I used this formula to get the horizontal travel at 0º, if the distance to the target is lower than that, the angle should be negative with the same value that a launch with negative height and gravity.
And to calculate the time of flight:
v0 cos(α) t = d
t = d / v0 cos(α)
function MinTravel(g, v0, h)
return v0 * math.sqrt(math.abs(2 * h / g))
end
function ProjectileMotionAux(g, v0, d, h)
local phase = math.atan2(d, math.abs(h))
local denom = math.sqrt(h * h + d * d)
local coef = (g * d * d) / (v0 * v0) - h
local angle = (math.pi / 2) - (math.acos(coef / denom) + phase) / 2
local time = d / (v0 * math.cos(angle))
return math.deg(angle), time
end
function ProjectileMotion(g, v0, d, h)
if h > 0 and d < MinTravel(g, v0, h) then
local angle, time = ProjectileMotionAux(-g, v0, d, -h)
return -angle, time
end
return ProjectileMotionAux(g, v0, d, h)
end