Find shortest turnaround between two angles in 2D

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By FunApple

I’m making top down space game where player command spaceships and found the problem with finding shortest angle between ship’s current angle and angle to required vector.
The problem comes with how godot uses Vector2.angle() method which I use for finding required angle to rotate ship to. Upper part of the image shows results (in degrees after using rad_to_deg) of using .angle method on Vector2. So GD get value clamped from ~ -180 and 180 which is near Vector (.0, -1) to near 0 value at Vector (.0, 1). Current ship’s rotation is just rotation value of CharacterBody2D. For rotation I simply use rotation += value * delta and because of gameplay mechanics I cannot use lerp methods. And I stuck with finding the closest path from current ship’s rotation to required one.
For example: current ship’s rotation is 270 degrees (looking up) and I need to rotate it to let’s say 190 degrees (to the left, 9:30 o’clock). .angle will return -170 degrees and calculating shortest path becomes hard because in math it’s 270 - -170 = 440 deg but really ship needs to be turned CCW by just 80 degrees. Or see another example on image.
Same problem when ship is let’s say at 350 deg and required angle is 0: by math it’s -350 CCW but really ship needs to be turned by 10 CW.

So my question is: how to find real closest angles between Vectors or rotations? I just didn’t found any methods for that built-in.

enter image description here

:bust_in_silhouette: Reply From: jgodfrey

There’s bound to be a much more elegant solution, but something like this (untested and very brute-forcey function) might work:

func shortest_rotation(ang: float) -> float:
	var new_ang = fmod(ang, 360)
	if abs(new_ang) > 180:
		if new_ang > 0:
			new_ang -= 360
		else:
			new_ang += 360
	return new_ang

Pass in your originally calculated angle and (with luck) the return value is what you’re after… :slight_smile:

Note, I just edited the above code to potentially add/subtract 360 rather than 180 (which was obviously wrong)…

jgodfrey | 2023-05-06 19:16