Playing complete animation once we press space once

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

Hi, i am trying to play the animation “roll” completely until it finished instead of it being played onlye once i press the spacebar, however the “roll” animation will immideiatly go to the “run” state once i relase the spacebar
code:

Code:

func _physics_process(delta):
var axis = get_input_axis()
if axis==Vector2.ZERO: 
	 
	apply_friction(acceleration * delta)
	$gun.show()
	$Movement.play("idle")
else:
	apply_movement(axis*acceleration*delta)
	if(Input.is_action_pressed("ui_space")):
		$gun.hide()
		$Movement.play("roll")
                 #yield($Movement, "animation_finished")
		
	else:
		$gun.show()
		$Movement.play("run")
	
motion = move_and_slide(motion)
:bust_in_silhouette: Reply From: Lethal0428

Try replacing Input.is_action_pressed("ui_space") with Input.is_action_just_pressed("ui_space")

:bust_in_silhouette: Reply From: deaton64

Hi,
I think it’s because as soon as you release the space bar, the next frame will process again and so the logic will play the run animation (or idle).
You might need to change the logic flow, but I think you need to do something like:
set a flag bool to true when you want to roll and do the roll animation.
Only do the other movement things when the flag is set to false.
Have an signal for the roll animation complete, to set the flag back to false.

how can i make a signal for the roll animation? i am new to game deva godot sorry for my confusion!

Rashid | 2020-07-14 07:41

With animated sprites and an animation player scene, you can add signals for the animation_finished.
Select the scene, then the node tab, right click on the animation finished option and connect the signal.

What are you using to animate?

deaton64 | 2020-07-14 12:51

i have animatedsprite and inside it, i have three animations (roll,run,idle)!

Rashid | 2020-07-14 19:55

You may want to checkout the animation state machine. That might work better with what you are trying to achieve.
You can flip between animations to match your character and decide if animations can change at any time or once an animation has completed.

Godot 3.1 - State Machine (Animation Tree) Tutorial

Kids Can Code - Controlling Animation States

deaton64 | 2020-07-14 20:53

hi i tried using signals but i am lost! here is what i have ended up with, i made a signal that will call a function everytime we press spacebar but my character vanishes!

    extends KinematicBody2D
var max_speed=170
var acceleration = 2000
var motion = Vector2.ZERO
onready var player = $Movement
signal isRolling


func _physics_process(delta):
	$Movement.connect("isRolling", self, "onRollSignal")
	var axis = get_input_axis()
	if axis==Vector2.ZERO:  
		apply_friction(acceleration * delta)
		$gun.show()
		$Movement.play("idle")
	else:
		apply_movement(axis*acceleration*delta)
		if(Input.is_action_pressed("ui_space")):
			emit_signal("isRolling")
			queue_free()
		else:	
				$gun.show()
				$Movement.play("run")
	motion = move_and_slide(motion)
	
func onRollSignal():
	$gun.hide()
	$Movement.play("roll")

Rashid | 2020-07-15 13:49

it’s vanishing cos you’re freeing it : queue_free()
Can you upload your project somewhere?

deaton64 | 2020-07-15 13:56

really appreciate your help i will try to upload it on a google drive now

Rashid | 2020-07-15 14:32

So if you copy the code below it should work. You might need to change the signal for Movement animation_finished() to connect to func _on_Movement_animation_finished() -> void:
I’m not sure if that’s what your code did originally.
is this function, I was testing for just the roll animation, but it wasn’t always detecting the right one, so it had to be a catch all.

I don’t think this is the best way to do this, as you can move with the space bar held down and the sprite looks like it’s idle for a second until the roll kicks in. Maybe have a look at some tutorials for a state machine with animated sprite.

extends KinematicBody2D
var max_speed=170
var acceleration = 2000
var motion = Vector2.ZERO
onready var player = $Movement
var isRolling = false # set to true if the sprite is rolling

func _physics_process(delta):
	#var roll = Input.is_action_pressed("ui_space")
	var axis = get_input_axis()
	if axis == Vector2.ZERO:
		apply_friction(acceleration * delta)
		$gun.show()
		$Movement.play("idle")
	else:
		apply_movement(axis*acceleration*delta)
		if !isRolling: # if the sprite isn't rolling, it can run
			$gun.show()
			$Movement.play("run")
	if Input.is_action_pressed("ui_space") and !isRolling: # only roll if the sprite isn't rolling
			isRolling = true # set that the sprite is rolling
			$gun.hide()
			$Movement.play("roll")

	motion = move_and_slide(motion)


func _on_Movement_animation_finished() -> void:
	# we're here because any animation has stopped
	isRolling = false # stop rolling


func get_input_axis():
	var axis = Vector2.ZERO
	axis.x=int(Input.is_action_pressed("ui_right"))-int(Input.is_action_pressed("ui_left"))
	axis.y=int(Input.is_action_pressed("ui_down"))-int(Input.is_action_pressed("ui_up"))
	return axis.normalized()


func apply_friction(amount):
	if motion.length()>amount:
		motion -=motion.normalized()*amount
	else:
		motion=Vector2.ZERO


func apply_movement(acceleration):
	motion +=acceleration
	motion = motion.clamped(max_speed)

deaton64 | 2020-07-15 22:01