Okay, this was a doozy. In case anyone finds this thread looking for an answer, here's how I did it eventually. Not saying it's the best way to do it, but after almost four hours of "what the fluff is even happening?!?" it works.
This first function calculates the angle from the missile to its target. I'm converting from rad to degree because I can't think in rad. It should be noted that if the target is below the missile, the angle is between 0 and 180, if it is above, the angle will be between 0 and -180. This caused me some issues.
The target_path check is just there in case the missile is still there but the target is destroyed prematurely. It is filled in the function that selects a target.
If anyone asks, I tried the angle_to() function, but for some reason the angles it returned were all over the place and never correct.
Also, apparently markdown is bugged, when I put something in a code block, it removes all line breaks.
func get_angle_to_target() -> float:
var angle = 0.0
if has_node(target_path):
angle = rad2deg((target.position - position).angle())
return angle
The second function calculates the difference between the angle to the target and the angle the missile is facing.
func get_angle_delta() -> float:
var angle_delta = 0.0
if get_angle_to_target() < 0:
angle_delta = global_rotation_degrees - get_angle_to_target()
else:
angle_delta = get_angle_to_target() - global_rotation_degrees
return angle_delta
This is the actual rotation and movement:
func _physics_process(delta):
if detect_targets().size() > 0:
if !has_node(target_path):
target = get_target(detect_targets())
if get_angle_to_target() < 0:
if get_angle_delta() <= 0 || get_angle_delta() > 180:
rotation_degrees += delta * turn_rate
else:
rotation_degrees -= delta * turn_rate
else:
if get_angle_delta() <= 0 || get_angle_delta() > 180:
rotation_degrees -= delta * turn_rate
else:
rotation_degrees += delta * turn_rate
velocity = get_transform().x.normalized() * speed
position += velocity