Help with tweening a rotation past 180 degrees

Godot Version

4.3

Question

I am creating a 2D topdown shooting game where the player’s arm rotates around their body to look at the mouse cursor. When the player shoots I want the gun to rotate up for a bit for recoil then return to the position looking at the mouse cursor.

I have done this by tweening from the current arm rotation to the arm rotation + 60 degrees.

This works everywhere except for the bottom left, where instead of going past 180 degrees into the negatives, it loops back around the opposite way. I first thought this was due to godot not knowing how to handle a rotation value if it was higher than any value in the unit circle (e.g. 160 degrees + 60 would be 220), so I tried to fix it with math.

However I know think its due to tween, is there any way to get tween to behave how I want it to?

here’s my code:

func play_tween():
	#adjust for if mouse is on left or right
	var calculated_angle
	if player_sprite.global_position > get_global_mouse_position(): 
		calculated_angle = deg_to_rad(convert_angle(arm_sprite.global_rotation))#left side
	else:
		calculated_angle = deg_to_rad(-60) + arm_sprite.global_rotation #right side
	#play tween
	var tween = create_tween()
	tween.tween_property(arm_sprite, 'global_rotation', calculated_angle, 1)
	tween.tween_property(arm_sprite, 'global_rotation',arm_sprite.global_rotation, 0.2)

func convert_angle(starting_angle : float):
	starting_angle = rad_to_deg(starting_angle) 	#converts to degrees
	var end_angle = starting_angle + 60 			#add 60 degrees to starting angle
	if end_angle > 179: 							#checks if angle will go over 180 degrees and into the negatives
		var angle_increase = end_angle + -179	#takes difference between starting angle and threshold away
		end_angle = -179 + angle_increase 		#increases angle past threshold
	return end_angle

Incorrect result I am currently having:

Result that I want:

Thank you!

A tween simply interpolates between two value, i.e. it starts at some value and then goes step by step to some target value.

Lets say the current rotation is 150. If we plug this into your convert_angle, it returns 150 + 60 - 179 - 179 = -148 - so the tween interpolates from 150 ‘down’ to -148, i.e. 298 deg counterclockwise. This is the ‘looping back around’ you are experiencing.

As I understand it, what you are actually trying to achieve is, that when the mouse is to the right of the player, it should rotate counterclockwise (i.e., -60deg), and clockwise (i.e., +60deg) when it’s to the left:

var calculated_angle
if player_sprite.global_position.x > get_global_mouse_position().x: 
	calculated_angle = arm_sprite.global_rotation + deg_to_rad(60) #left side
else:
	calculated_angle =  arm_sprite.global_rotation - deg_to_rad(60) #right side
#play tween

Another problem is the ‘rotating back’. You are currently just rotating the sprite to the sprites current rotation. You should rotate to the mouse position.

Btw. the unit circle does not have anything to do with 180 deg. It’s simply a circle with radius 1.