Stop movement and play animation when stamina goes to zero

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

Hello everyone. I started yesterday with Godot and I am trying to make a game. I have created the following code for tutorial purposes (I found the character online and I am using it only for personal and learning reasons). So the character has sprites for moving left/right/jumping and a stamina bar. Each movement depletes the stamina bar, and when idle the character replenishes stamina. What I want to do is that when the character reaches stamina = 0 to stop for the rest animation to play. The animation only plays if I keep the jump button pressed. The stamina instantly replenishes when not pressing a button, and thus I can’t get the animation to play. Even when the stamina is 0, the character keeps moving left and right. I tried to set up speed = 0 and vel.x = 0 but nothing worked to get the animation to play. I looked at some recommendations regarding a timer, but couldn’t figure out how to add it.
Any help with this is greatly appreciated.

extends KinematicBody2D

var score : int = 0

var speed : int = 200
var jumpForce : int = 300
var gravity : int = 800

var vel : Vector2 = Vector2()

onready var sprite : AnimatedSprite = get_node("AnimatedSprite")

#sstamina?
var stamina = 100
var current_angle = -1.6
var min_angle = -1.6
var max_angle = 4.7
func _process(delta):
	if Input.is_action_pressed("move_left") or Input.is_action_pressed("move_right") or Input.is_action_pressed("jump"):
		update()
	if Input.is_action_pressed("move_left"):
		stamina -= 0.25
	elif Input.is_action_pressed("move_right"):
		stamina -= 0.25
	elif Input.is_action_pressed("jump"):
		stamina -= 30
	else:
		stamina += 0.5
		update()
	stamina = clamp(stamina,0,100)
	
	var value = ((min_angle * -1) + max_angle)/100
	current_angle = max_angle - (stamina * value)
	#####end of stamina
	
	
func _physics_process(delta):
	vel.x = 0
	#movement imputs
	if Input.is_action_pressed("move_left") and is_on_floor():
		vel.x -= speed
		$AnimatedSprite.play("walk")
	
	elif Input.is_action_pressed("move_right") and is_on_floor():
		vel.x += speed
		$AnimatedSprite.play("walk")
	elif Input.is_action_pressed("move_right") and not is_on_floor():
		$AnimatedSprite.play("jump")
		vel.x += speed
	elif Input.is_action_pressed("move_left") and not is_on_floor():
		$AnimatedSprite.play("jump")
		vel.x -= speed
	elif not is_on_floor():
		$AnimatedSprite.play("jump")
	elif is_on_floor() and stamina == 0:
		speed = 0
		$AnimatedSprite.play("rest")
	else:
		speed = 200
		$AnimatedSprite.play("Idle")
		
	if Input.is_action_just_pressed("jump") and is_on_floor():
		vel.y -= jumpForce
	
	
	
	#applying velocity
	vel = move_and_slide(vel,Vector2.UP)
	#gravity
	vel.y += gravity * delta
		
	#applying direction of sprite
	if vel.x < 0:
		sprite.flip_h = true
	elif vel.x > 0:
		sprite.flip_h = false

I uploaded a gif of the issue: Imgur: The magic of the Internet

:bust_in_silhouette: Reply From: CassanovaWong

It looks like your else statement (_physics_process(delta)) is interrupting your other animations… cause that’s what is running when you’re not pressing the other keys… You need to write it so as to play that idle or rest animation only after the other animations completed. maybe just check if the sprite is playing and only run idle if it is stopped, or something.

Same sort of issue with the else statement in your _process function… you might change it to make sure the stamina only replenishes after your rest animation completes. Maybe using a yield (or await, in Godot 4) or signals…

Side note: Look into state machines, and Animation Tree for more information on this kind of thing. Also, using the else statement less can make it easier to track down hidden glitches like this.

i see what you mean. But i must force the resting animation when stamina goes to 0 which happens when the player is moving left or right

Herc34es | 2022-02-23 15:59