Hello!
I'm aware of the rotation coordinates for Godot going from 0 -> 180 then -180 ->0 for a full rotation. However, I have a spaceship CharacterBody2D that I am making follow the mouse and there is a noticeable jerk to the opposite direction when the mouse crosses that 180 deg point.
Is there a simple fix or previous discussion post regarding this?

    xyz

    mouse_pos = get_global_mouse_position()
    var mouse_direction = mouse_pos - position
    var mouse_angle = mouse_direction.angle()
    
    global_rotation = lerp_angle(global_rotation, mouse_angle, 0.05)
    • xyz replied to this.

      OD-17 Slerp the direction vectors instead of lerping angles.

      @xyz
      Thanks that sounds like what I need. Do I have to keep track of a prev_mouse_dir and cur_mouse_dir variable to do that?

      @Tomcat
      look_at() is great I'm just trying to get that fluid lag motion when it rotates so it's not always snapped directly towards the mouse. xyz sounds right to slerp the direction vectors, just a newbie here.

      • xyz replied to this.

        OD-17 Do I have to keep track of a prev_mouse_dir and cur_mouse_dir variable to do that?

        No. If you want it to behave like your current code (delay etc.) then slerp from current direction to direction determined by mouse position. If the pointing axis is x, then the current direction is node's transform x basis, i.e. transform.x. In other words you need to spherically interpolate between current x basis and wanted x basis.

        24 days later

        I couldn't figure out how to slerp the direction vector but ChatGPT helped with a work around using angles. There are easier ways to do this and the transition point is not perfect but overall the effect is nice. Although I would like to figure out how to slerp the direction vectors. Code below:

        class_name RotateToMouseComponent
        extends Node
        
        @export var actor : Node2D
        
        var target_rotation : float = 0.0
        
        func _process(_delta):
        	# Get the current mouse position
        	var mouse_position = actor.get_global_mouse_position()
        	# Calculate the direction vector from the actor position to the mouse position
        	var direction = (mouse_position - actor.global_position).normalized()
        	# Calculate the angle between the current direction and the horizontal axis (1, 0)
        	var mouse_angle = direction.angle()
        	# Calculate the shortest angle difference for smooth rotation
        	var current_rotation = actor.global_rotation
        	var difference = shortest_angle_difference(current_rotation, mouse_angle)
        	# Check if the absolute difference is greater than 90 degrees
        	if abs(difference) > PI / 2:
        		# Rotate in the opposite direction if the angle difference is more than 90 degrees
        		target_rotation = current_rotation - sign(difference) * PI
        	else:
        		# Set the target rotation based on the shortest angle difference
        		target_rotation = current_rotation + difference
        
        	# Apply rotation towards the target angle
        	actor.global_rotation = lerp_angle(current_rotation, target_rotation, 0.02)
        	
        
        func shortest_angle_difference(a: float, b: float) -> float:
        	var diff = float_modulo((b - a + PI), TAU) - PI
        	if diff < -PI:
        		return diff + TAU
        	elif diff > PI:
        		return diff - TAU
        	else:
        		return diff
        
        func sign(x: float) -> float:
        	return x / abs(x) if x != 0 else 0
        
        func float_modulo(x: float, y: float) -> float:
        	return x - y * floor(x / y)
        • xyz replied to this.

          OD-17 I couldn't figure out how to slerp the direction vector

          Not sure what there is to figure out really. 2D slerp is just a "circular" interpolation between two vectors and Vector2 has a method that does it.

          interpolated_direction = direction1.slerp(direction2, weight)

          Doing it with angles is what we wanted to avoid in the first place because. Using slerp makes it much easier and simpler. However I won't go into "improving" GPT's code, out of mere principle.

            xyz Sorry, new to using slerp. It makes me thirsty! I am certainly overcomplicating and as a result this is likely a silly question, however, if I have the code below - which still has the jerk at 180 deg but rotates nicely- how do I actually update the ship direction to the interpolated direction without referencing the angle as below.. You mentioned basis earlier, do I need quaternions?

            	var mouse_position : Vector2 = actor.get_global_mouse_position()
            	var mouse_direction : Vector2 = (mouse_position - actor.global_position).normalized()
            	var interpolated_direction = player_ship_stats.current_normalized_direction.slerp(mouse_direction, 0.02)
            	
            	player_ship_stats.current_normalized_direction = interpolated_direction
            
                   #different rotations that work the same but use angles
                   #actor.look_at(actor.global_position + interpolated_direction)
            	
                   actor.global_rotation = interpolated_direction.angle()