Top Down, 2D, trying to rotate the player head separate from the body while the body slowly realigns rotation with the head.

Godot Version

4.22

Question

Hello.
I am new to Godot 4.
I used to use Godot back in high school, I assume it was Godot 3, I am not certain.
I have a simple top down shooter in mind.
I want the player to be able to directly look around the environment with their head, but I want the body to take some time to realign with where the head is facing.
I have found only partially similar issues for older versions of Godot, and have not found my exact issue here.
I want the body to move linearly according to WASD, and already have very basic movement for this scripted:

extends CharacterBody2D

var speed = 200

func get_input():
	var input_direction = Input.get_vector("move_left", "move_right", "move_up", "move_down")
	velocity = input_direction * speed

func _physics_process(delta):
	get_input()
	move_and_slide()

The character body 2D is the root node.
I have 2 animated sprite 2D nodes with placeholder assets.
1 for the head,1 for the body, and a collision shape for the body.
I want faster head turns to mean faster body rotation, while slower turns remain almost aligned with head.
I want the movement to, in a phrase, drag and have inertia.
I am assuming parabolic math is involved.

I am only concerned right now with separating the rotation of the head and body of the player and making it move in this fashion.
I believe I can make enemies do this differently on my own if I can understand how to separate these two parts and control this difference in rotation.

Summary: I want the player’s head rotated by looking at the mouse, while the body rotates to align to where the head is looking at.

The end goal is for weapons to fire or swing straight forward from the body, while simultaneously being affected separately by their own accuracy penalties or melee range. There will be a vision cone for the head of the player, but that is irrelevant for this problem. This separation of aiming and sight is the reason I am trying to separate the head’s and body’s rotations.

Thank in advance for your time.

To slowly align to the head rotation you can use the lerp(from, to, weight)method. You can get the mouse position with get_global_mouse_position()

1 Like

Thank you.
I knew about get_global_mouse_postion(), but not about Godot’s interpolation methods.
This was exactly what I needed.

1 Like

I’ve since discovered that lerp_angle is superior to lerp for rotation, as lerp on it’s own will try and jerk 180 degrees if the x axis is crossed during rotation, leading to weird clipping or movements, while lerp_angle tries to maintain a smooth rotation across all 360 degrees. This is what I have for the rotation code.

extends CharacterBody2D
@onready var head = $Head
@onready var body = $Body
@onready var collision = $CollisionShape2D

func get_input():
	var head_rotation = head.rotation
	var body_rotation = body.rotation
	head.look_at(get_global_mouse_position())
	body.rotation = lerp_angle(body_rotation, head_rotation, 0.1)
	
func _physics_process(delta):
	get_input()
	move_and_slide()

I am going to try to find a way to slightly interpolate the difference between the look_at(mouse) and the head’s rotation, but for the time being, it looks good.

1 Like