Create rotating animation when changing direction in 8-direction movement 2d

Godot Version

3.5.3

Question

I’m making an 8-direction movement for top-down game following this video tutorial: “https://www.youtube.com/watch?v=o-eZSUkMesg”. Here is my code:

extends KinematicBody2D

var acceleration = 600
var friction = 600
var maxspeed = 60
var velocity = Vector2.ZERO

func _process(delta):
	movement(delta)


func movement(delta):
	var input = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down").normalized()
	movement_animation(input)
	if input == Vector2.ZERO:
		if velocity.length() > (friction*delta): velocity -= velocity.normalized()*friction*delta  
		else: velocity = Vector2.ZERO
	else:
		velocity += (input*acceleration*delta)                                                  
		velocity = velocity.limit_length(maxspeed)       
	velocity = move_and_slide(velocity)


func movement_animation(input):
	if input == Vector2.ZERO:
		$AnimationTree.get('parameters/playback').travel('idle')
	else:
		$AnimationTree.get('parameters/playback').travel('run')
		$AnimationTree.set('parameters/idle/blend_position',input)
		$AnimationTree.set('parameters/run/blend_position',input)

It looks fine but I would like it to be smoother by turning gradually from the current direction to the target direction when changing direction.

For example, if the character is facing right and I change direction to the left, it will run the right-up → up → left-up animation in turn and then finally run the left animation.

It should look like the shooting game character’s animation below. At the bottom is my character so you can easily compare.
https://www.youtube.com/shorts/ViI9CrLUqyw

Hello! There are 2 possible ways to achieve this I can think of:

  • you create a rotation animation and use an animation State Machine. You create a “rotating CW” and “rotating CCW” states that plays when you go from the states “facing up” to “facing down”, “facing left” to “facing right”, etc.

  • you “cheat” and don’t actually make a pixel perfect game and use a tween animation to smoothly rotate from the current orientation to the goal orientation.

The game you showed as an example might be using option 2; but I can’t be sure.

Hmmm, you can use animation tree, it is the best and easy way

I have changed something and use rotated() to rotate the direction vector. Now it works perfectly.
Here is new code:

extends KinematicBody2D

var acceleration = 600
var friction = 600
var maxspeed = 60
var velocity = Vector2.ZERO
var current_direction = Vector2(1,0)

func _process(delta):
	movement(delta)

func movement(delta):
	var input = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down").normalized()
	movement_animation(input,delta)
	if input == Vector2.ZERO:
		if velocity.length() > (friction*delta):velocity -= velocity.normalized()*friction*delta  
		else:velocity = Vector2.ZERO
	else:
		velocity += (input*acceleration*delta)                                                  
		velocity = velocity.limit_length(maxspeed)       
	velocity = move_and_slide(velocity)

func movement_animation(input,delta):
	if current_direction != input:
		if abs(current_direction.angle_to(input)) < (20*delta*PI/4) and input != Vector2.ZERO:
			current_direction = input
		elif abs(current_direction.angle_to(input)) > (20*delta*PI/4):
			var rotation_direction = -1 if current_direction.angle_to(input) < 0 else 1
			current_direction = current_direction.rotated(20*delta * rotation_direction*PI/4)
	if input == Vector2.ZERO:
		$AnimationTree.get('parameters/playback').travel('idle')
	else:
		$AnimationTree.get('parameters/playback').travel('run')
		$AnimationTree.set('parameters/idle/blend_position',current_direction)
		$AnimationTree.set('parameters/run/blend_position',current_direction)