2D RPG attack animation instantly finishing upon beginning of animation

Godot Version

4.4

Question

Hey everyone. I am very very new here so ive been watching some tutorials online and trying to figure out how to make a game. Its a little 2d rpg.
I have been following this one tutorial but i cant figure out why my attack animation on my animatedSprite2d is happening so fast. I want to slow it down so you can see it, it just begins and then instantly goes back to its idle or run animation . The script is probably very poorly written so my apoligies in advance.
I would also like the attack animation to face left or example if my character is facing left. I got it to work for the run animations but cant figure it out for the attack.
Thanks for any tips or advice given, much appreciated.

class_name player extends CharacterBody2D

var move_speed : float = 250
var enemy_inattack_range = false
var enemy_attack_cooldown = true
var health = 100
var player_alive = true
var player_state
var attack_ip = false #(in progress)

func _physics_process(delta: float) → void:
player_movement(delta)
enemy_attack()
attack()

if health <= 0:
	player_alive = false #go back to spawn or main screen.
	health = 0
	print("player has been killed")

func player_movement(delta):
var direction =Input.get_vector(“left”, “right”, “up”, “down”)
if Input.is_action_pressed(“right”):
%AnimatedSprite2D.flip_h = false
elif Input.is_action_pressed(“left”):
%AnimatedSprite2D.flip_h = true

if direction.x == 0 and direction.y == 0:
	player_state = "idle"
elif direction.x != 0 or direction.y != 0:
	player_state = "run"

velocity = direction * move_speed
move_and_slide()

play_anim(direction)

func play_anim(dir):
if player_state == “idle”:
%AnimatedSprite2D.play(“idle”)
if attack_ip == false:
%AnimatedSprite2D.play(“idle”)
if player_state == “run”:
%AnimatedSprite2D.play(“run”)
if attack_ip == false:
%AnimatedSprite2D.play(“run”)
func player():
pass

func _on_player_hitbox_body_entered(body: Node2D) → void:
if body.has_method(“enemy”):
enemy_inattack_range = true

func _on_player_hitbox_body_exited(body: Node2D) → void:
if body.has_method(“enemy”):
enemy_inattack_range = false

func enemy_attack():
if enemy_inattack_range and enemy_attack_cooldown == true:
health = health - 20
enemy_attack_cooldown = false
$attack_cooldown.start()
print(“health -20”)

func _on_attack_cooldown_timeout() → void:
enemy_attack_cooldown = true

func attack():

if Input.is_action_just_pressed("attack"):
	global.player_current_attack = true
	attack_ip = true
	$AnimatedSprite2D.flip_h = false
	$AnimatedSprite2D.play("attack_front")
	$deal_attack_timer.start()

func _on_deal_attack_timer_timeout() → void:
$deal_attack_timer.stop()
global.player_current_attack = false
attack_ip = false

Make sure to format your code pastes to they are easy to read on the forum; I suspect indentation will matter for your issue

this has no type. I would set it to int and create an enum.


enum {IDLE, WALK, ATTACK, ETC}
var player_state : int = 0

there are no states used in the script. a state machine is essential for a game character. just use a match:

func _physics_process(_delta) -> void:
	#...
	match player_state:
		WALK:
			if direction:
				velocity = direction * move_speed
			move_and_slide()
		JUMP:#or whatever
			move_and_slide()
		_:#0
			move_and_slide()

you are also using an AnimatedSprite2D. don’t. AnimatedSprite2D is very limited and I only recommend it for explosions and things that must happen once.
for a character use a Sprite2D, then add an AnimationPlayer and create the animations there. then add an AnimationTree to manage the state machine of the animations. you still need a state machine for the character script but to set movement.
with an AnimationTree it is best to use expressions. while they add this new godot 4 feature to the documentation, here’s my tutorial:
https://godotforums.org/d/39521-this-is-how-to-use-animationtree-state-machine-transitions-with-expressions

you can animate EVERYTHING with the animationPlayer. this includes variables in your script.
I would use a variable to tell the player to not move while the attack is happening. or manage attack independently from it.

Thank you very very for the advice, much appreciated!!

Thanks mate, very much appreciated!