AnimatedSprite only plays the first frame

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

Hey all. I’m fairly new to this engine, but mostly enjoying it so far. However, I’ve hit a major roadblock and it’s driving me nuts, and I can’t seem to find a concrete solution for it.

I’m currently prototyping a 2D action platformer and when I press the key to attack, the animation only plays the first frame and then goes right back to idle. I’ve read it’s because the attack animation and the idle animation are going at the same time, but I cannot for the life of me figure how to fix it. Every answer I see is either too vague in some way or they’re using the AnimationPlayer node. I am using AnimatedSprite.

My movement code where the idle is:

if Input.is_action_pressed("ui_right"):
	if attacking == false:
		if crouched == false:
			if defending == false:
				velocity.x = SPEED
				$AnimatedSprite.play("Walk")
				$AnimatedSprite.flip_h = false
elif Input.is_action_pressed("ui_left"):
	if attacking == false:
		if crouched == false:
			if defending == false:
				velocity.x = -SPEED
				$AnimatedSprite.play("Walk")
				$AnimatedSprite.flip_h = true
else:
	velocity.x = 0
	if on_ground == true:
		$AnimatedSprite.play("Idle")

My attack code:

	if Input.is_action_just_pressed("attack"):
	if defending == false:
		$AnimatedSprite.play("Light_Attack_1")
		attacking = true
		velocity.x = 0
else:
	attacking = false

Any help to fix this would be greatly appreciated!

:bust_in_silhouette: Reply From: CalmTurtle

What is your on ground bool doing? Outside looking in, it seems like your on ground might be true, causing your animation to go idle. The is action just pressed is a one shot function of sorts. Guessing here, but it seems like after you hit the key you play your attack animation but then your on ground is true which sends it back to idle.

HUGE recommendation: You should put your animations in a process update and disconnect it from your movements (which should be in your physics update).

That’s what I figured might be going on, but I just don’t know how to fix it.

As you said, I moved all my animation code to a process update. Don’t know if this’ll help or not, but here’s my entire code right now:

extends KinematicBody2D

const SPEED = 500
const GRAVITY = 40
const JUMP = -1500
const FLOOR = Vector2(0, -1)

var velocity = Vector2()
var on_ground = false
var crouched = false
var attacking = false
var defending = false

func _physics_process(delta):

#MOVEMENT	

if Input.is_action_pressed("ui_right"):
	if attacking == false:
		if crouched == false:
			if defending == false:
				velocity.x = SPEED
elif Input.is_action_pressed("ui_left"):
	if attacking == false:
		if crouched == false:
			if defending == false:
				velocity.x = -SPEED
else:
	velocity.x = 0

#JUMP

if Input.is_action_just_pressed("ui_select"):
	if on_ground == true:
		velocity.y = JUMP
		on_ground = false
	
velocity.y += GRAVITY
	
velocity = move_and_slide(velocity, FLOOR)

#ATTACK

if Input.is_action_just_pressed("attack"):
	if defending == false:
		attacking = true
		velocity.x = 0
else:
	attacking = false
	

#CROUCH

if Input.is_action_pressed("ui_down"):
	if on_ground == true:
		if attacking == false:
			velocity.x = 0
			crouched = true
else:
	crouched = false

#DEFEND

if Input.is_action_pressed("defend"):
	if on_ground == true:
		if attacking == false:
			velocity.x = 0
			defending = true
else:
	defending = false

func _process(delta):

#MOVEMENT

if Input.is_action_pressed("ui_right"):
	if attacking == false:
		if crouched == false:
			if defending == false:
				$AnimatedSprite.play("Walk")
				$AnimatedSprite.flip_h = false
elif Input.is_action_pressed("ui_left"):
	if attacking == false:
		if crouched == false:
			if defending == false:
				$AnimatedSprite.play("Walk")
				$AnimatedSprite.flip_h = true
else:
	if on_ground == true:
		$AnimatedSprite.play("Idle")
		
#JUMP

if is_on_floor():
	on_ground = true
else:
	on_ground = false
	if velocity.y < 0:
		$AnimatedSprite.play("Jump")
	else:
		$AnimatedSprite.play("Fall")
		
#ATTACK

if Input.is_action_just_pressed("attack"):
	if defending == false:
		$AnimatedSprite.play("Light_Attack_1")

#CROUCH

if Input.is_action_pressed("ui_down"):
	if on_ground == true:
		if attacking == false:
			$AnimatedSprite.play("Crouch")

#DEFEND

if Input.is_action_pressed("defend"):
	if on_ground == true:
		if attacking == false:
			$AnimatedSprite.play("Defend")

Sorry, still new to this formatting thing.

PhantomDragon64 | 2019-04-02 23:26

So this isn’t gonna be a perfect answer but there are a few things that look like they could be optimized a bit. There are functions built into godot that would take care of your on ground stuff (if your not moving down, you must be on the ground for instance).

There is a tutorial that is absolutely perfect for what you are asking. It’s behind a $10.99 pay wall but I can promise it is worth the money. Check out lesson 5. The examples in that lesson alone will be worth the price of admission. Good luck.

CalmTurtle | 2019-04-03 00:05