• 2D
  • Animated Sprite 8 directional

Hello, Im starting a Rpg and im using an animated sprite for my main player since all his movements are too big to fit on one sprite sheet. I saw videos on YouTube and they all use animation player with an animation tree. In the end i was able to show the up, down, left, right movement and idle animations but cant figure out the diagonals.

You probably want to do something using the input_vector code below at line 32 instead of checking each individual input, as this will allow you to do some processing to more easily detect diagonal movement. It will require some adjusting for idle animations though, but if you store the last non zero value of input_vector then you can use it for telling which idle animation to choose.

There are many ways to do this. The easiest way is to do some conditions to tell if movement is diagonal or not, and then which direction. I have not tested it, but something like this should work:

onready var _animated_sprite = $AnimatedSprite
var last_direction = Vector2.ZERO

func _physics_process(delta):
	var input_vector = Vector2.ZERO
	input_vector.x = Input.get_action_strength(“ui_right”) - Input.get_action_strength(“ui_left”)
	input_vector.y = Input.get_action_strength(“ui_down”) - Input.get_action_strength(“ui_up”)
	Input_vector = input_vector.normalized()
	
	# if we are moving...
	if input_vector.length_squared() > 0:
		# Store the direction for use later when needing
		# to choose the idle animation
		last_direction = input_vector
		
		# Diagonal movement
		if input_vector.x != 0 and input_vector.y != 0:
			# going down?
			if input_vector.y > 0:
				if input_vector.x > 0:
					_animated_sprite.play(“run_down_right”)
				else:
					_animated_sprite.play(“run_down_left”)
			else:
				if input_vector.x > 0:
					_animated_sprite.play(“run_up_right”)
				else:
					_animated_sprite.play(“run_up_left”)
		# Otherwise we are moving either horizontal or vertical, so its just a
		# matter of finding out which.
		# horizontal movement
		elif input_vector.x != 0:
			if input_vector.x > 0:
				_animated_sprite.play(“run_left”)
			else:
				_animated_sprite.play(“run_right”)
		# vertical movement
		else:
			if input_vector.y > 0:
				_animated_sprite.play(“run_down”)
			else:
				_animated_sprite.play(“run_up”)
	# if we are not moving, use the last known movement
	else:
		# Diagonal movement
		if last_direction.x != 0 and last_direction.y != 0:
			# going down?
			if last_direction.y > 0:
				if last_direction.x > 0:
					_animated_sprite.play(“idle_down_right”)
				else:
					_animated_sprite.play(“idle_down_left”)
			else:
				if last_direction.x > 0:
					_animated_sprite.play(“idle_up_right”)
				else:
					_animated_sprite.play(“idle_up_left”)
		# Otherwise we are moving either horizontal or vertical, so its just a
		# matter of finding out which.
		# horizontal movement
		elif last_direction.x != 0:
			if last_direction.x > 0:
				_animated_sprite.play(“idle_left”)
			else:
				_animated_sprite.play(“idle_right”)
		# vertical movement
		else:
			if last_direction.y > 0:
				_animated_sprite.play(“idle_down”)
			else:
				_animated_sprite.play(“idle_up”)

Hopefully this helps a bit :smile:

Thank you it worked perfectly! I came across another dilemma, eventually i would like to add a Roll, Damage, Death and Power change animation. Would i have to make a enum for those states I want the player to be in along with his movement and idle animations?

@LegendarySaintLos said: Thank you it worked perfectly! I came across another dilemma, eventually i would like to add a Roll, Damage, Death and Power change animation. Would i have to make a enum for those states I want the player to be in along with his movement and idle animations?

Awesome, I’m glad it worked.

For the different stuff, it really depends on how you want to do it. I would personally suggest using a state machine, or something similar, to handle this kind of thing as I find it a flexible solution for adding different states and animations. However, the best advice I can give is to go with whatever you think will work and/or what you are comfortable with, as that will be the best solution for your project :smile:

a month later

For future readers: You can make it by using an angle from Vector2. First (for educational purposes) create input Vector2:

inputVector.y = Input.GetActionStrength("Move_down") - Input.GetActionStrength("Move_up");
inputVector.x = Input.GetActionStrength("Move_right") - Input.GetActionStrength("Move_left");

Then calculate angle (0-360) from it:

yourAngle = Mathf.Rad2Deg(inputVector.AngleTo(Vector2.Down));  // For me Vector down as zero
yourAngle = yourAngle < 0 ? yourAngle + 360f : yourAngle;  // change -180 <-> +180 to 0 <-> 360
yourAngle = Mathf.Stepify(yourAngle, 45);  // Step it for 8 directions (360/8 = 45)
yourAngle = yourAngle == 360f ? 0f : yourAngle;  //360 and 0 are the same

Then if you have animations organised in angles like me:

CurrentAnimation = "Run_" + yourAngle;