Memorize sprite direction, sprite movement until end animation, make sprite speed equal all directions

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By BlackFenix06

Hi, I’m new to Godot, and I’m starting to learn how to use it, following different guides. For now, I’ve created a Player with eight different running animations (eight directions). Granted, I know that at the moment the script is probably very dirty (definitely), but at the moment I’m interested in learning. To clean it there is time to do it…

extends KinematicBody2D

const floor_normal : = Vector2(0, -1)

var speed : = 10000.0
var del : = 0.2
var velocity : = Vector2()
var target_speed_x : = 0.0
var target_speed_y : = 0.0

var directions : = "south"

onready var anim_sprite : = $anim_sprite as AnimatedSprite

func _process(delta):
	#print(directions)
	if velocity.x == 0 && velocity.y == 0:
		if anim_sprite.animation == "run_"+directions && anim_sprite.frame == anim_sprite.frames.get_frame_count("run_"+directions)-1:
			anim_sprite.play("idle_"+directions)
	else:
		anim_sprite.play("run_"+directions)

func _physics_process(delta):
	get_input(delta)
	
	velocity.x = lerp(velocity.x, target_speed_x, del)
	if abs(velocity.x) < 1:
		velocity.x = 0
	velocity.y = lerp(velocity.y, target_speed_y, del)
	if abs(velocity.y) < 1:
		velocity.y = 0
	velocity = move_and_slide(velocity, floor_normal)
	#print(velocity)
	
	var north = Input.is_action_pressed("ui_up")
	var south = Input.is_action_pressed("ui_down")
	var west = Input.is_action_pressed("ui_left")
	var east = Input.is_action_pressed("ui_right")
	
	var direction = Vector2()
	
	if north:
		direction += Vector2(0, 1)
	if south:
		direction += Vector2(0, -1)
	if west:
		direction += Vector2(-1, 0)
	if east:
		direction += Vector2(1, 0)
	direction = direction.normalized()
	
	var angle = rad2deg(direction.angle())
	if angle >= 0:
		angle = angle
	else:
		angle + 360

	if int(angle) == 0:
		directions = "east"
	elif int(angle) == -45:
		directions = "south_east"
	elif int(angle) == -90:
		directions = "south"
	elif int(angle) == -135:
		directions = "south_west"
	elif int(angle) == 180:
		directions = "west"
	elif int(angle) == 135:
		directions = "north_west"
	elif int(angle) == 90:
		directions = "north"
	elif int(angle) == 45:
		directions = "north_east"
	else:
		directions = "south"
	
func get_input(delta):
	target_speed_x = (Input.get_action_strength("ui_right") - Input.get_action_strength("ui_left")) * speed * delta
	target_speed_y = (Input.get_action_strength("ui_down") - Input.get_action_strength("ui_up")) * speed * delta

I currently have three problems that I can’t solve…

  1. When I release the movement commands, the sprite’s direction is set to east. This is caused by the angle returning to 0. What I would like instead is that the direction remain the same as it was set (so if the direction of the sprite moving was south, once released the key must stay south)
  2. At the moment I’m using a sprite and animation from the Factorio game as a placeholder, as I haven’t found many eight-way sprites on the net. The running animation consists of 22 frames. What happens at the moment is that if I release the run button, the sprite continues to run in place until the animation ends. What I would like instead is that the sprite continue to move in the current direction until the animation ends (even if the key has been released)
  3. The speed of the sprite diagonally increases with respect to the vertical or horizontal direction. How can I make it the same instead?

Thanks for your help.

:bust_in_silhouette: Reply From: AlexTheRegent
  1. You need variable to save last movement direction. Use this variable to set player’s facing direction.
  2. Hook animation_finished and stop player inside this signal, instead of key release.
  3. You need to clean your code, because you repeat your code like 2 or 3 times. You need to have normalized direction vector and then multiply it by speed.
var velocity = direction * speed```
and then you can call `move_and_slide` with `velocity`.

Also note that
move_and_slide - linear_velocity is the velocity vector (typically meters per second). Unlike in move_and_collide(), __you should not multiply it by delta__ — the physics engine handles applying the velocity.