Animated Sprite play an animation once from frame 0, then toggle back to idle animation?

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

Hi, I’m totally new to coding and making games. I’m working on a skateboard game in 2d.

I am using the Animated Sprite. I need a way to have an idle animation that plays, and then use inputs to trigger trick animations. The trick animations need to hide when they reach the final frame, and reset to frame 0 so that they play from the beginning when they’re called next.

I am trying to do something like this, but I am getting an error message that my last line of code is using an unexpected assign. That’s confusing because I am using the same command a few lines above, and that instance has no errors:

if Input.is_action_pressed("ui_Kickflip"):
	$Rolling.hide()
	$Kickflip.frame = 0
	$Kickflip.show()
	$Kickflip.playing = true
if $Kickflip.frame = 26
	$Kickflip.hide()
	$Rolling.show()
:bust_in_silhouette: Reply From: ZachMoldof

Figured it out, but I have no idea if this is a reasonable or efficient solution? I’m planning on having about 32 tricks in the demo version. I set the node to send a signal when the animation finishes, and I used a function to hide the trick animation and play my idle animation.

Using $Node.frame = 0 resets the animated sprite to the first frame. If you’re using a looping animation you don’t have to worry about it. But if you want to call an animation and have it play once, then you have to tell Godot to play that animation from Frame 0, otherwise it will just recall sprite with the last frame cued up.

if Input.is_action_pressed("ui_Kickflip"):
	$Rolling.hide()
	$Kickflip.frame = 0
	$Kickflip.show()
	$Kickflip.playing = true

func _on_Kickflip_animation_finished():
$Kickflip.hide()
$Rolling.show()

That frame = 0 part was what sent me googling, thanks for that.

I am still used to gotoAndStop() and gotoAndPlay() from the good old ActionScript days and was wondering why an animation wouldn’t play (after the first successful playing) even when told to.
This manual resetting feels a bit awkward, but as long as it works… :wink:

ChristianSF | 2020-08-01 12:51

:bust_in_silhouette: Reply From: Calamander

When using AnimatedSprite node you’re supposed to store your animations in one node and use AnimatedSprite.play("animationName") method (https://docs.godotengine.org/en/3.0/classes/class_animatedsprite.html#class-animatedsprite-play)
If you do that you don’t have to bother about hiding/showing nodes and you can also use animation_finished() event to restart your idle animation (which should be on loop unlike trick animations). Though you may want to add one extra frame to your trick animations because event triggers as soon as animation gets to the last frame so if you change it right away you may not be able to see it.
Overall it should be something like this:

func _process(delta):
	if Input.is_action_pressed("ui_Kickflip"):
	    $AnimatedSprite.play('Kickflip')
	elif Input.is_action_pressed("ui_OtherTrick"):
		$AnimatedSprite.play('OtherTrick')
	#elif ...

func _on_AnimatedSprite_animation_finished():
	if $AnimatedSprite.animation != 'Rolling':
		$AnimatedSprite.play('Rolling')

I suggest also to choose your idle animation in editor and check “playing” so it will start with idle animation right away.

Thanks G, much appreciate the tips.

ZachMoldof | 2018-11-10 19:38

func _on_AnimatedSprite_animation_finished():
if $AnimatedSprite.animation != 'Rolling':
    $AnimatedSprite.play('Rolling')

What is the exclamation mark doing? Is that saying “If the animation isn’t ‘Rolling’?”

Also, if there is any kind of introduction to script that you recommend, I would appreciate your insight.

ZachMoldof | 2018-11-10 20:58

Exactly. “Not equal”. Overall function means “When some animation is finished check if it is not idle animation that finished then start idle animation”.
As a reference you can use this:
http://docs.godotengine.org/en/3.0/getting_started/step_by_step/your_first_game.html
It explains step by step how to use AnimatedSprite for animation along with some other stuff.
First you create, name and fill your animations inside AnimatedSprite. Then in your script you define under what circumstances you change your animation and to which one. And then you connect AnimatedSprite signal animation_finished to your script so that you can restart your idle animation after trick is finished or maybe choose to restart trick animation (or don’t replace it with idle it if its looped by default) if you’re still in progress of performing your trick.
You may also consider using this instead for your animation:
Introduction to the 2D animation features — Godot Engine (3.0) documentation in English
its more flexible, but may be harder to start with.

Calamander | 2018-11-10 21:23

:bust_in_silhouette: Reply From: Sociopathix

I know this question is two years old and it doesn’t matter anymore, but I don’t usually know the answers to questions. Your unexpected assign is in your second if statement: “if $Kickflip.frame = 26” should be “if $Kickflip.frame == 26:”.

You’re missing a second equal sign and the colon at the end of the statement. The error is being called by the first issue, but the second will also call an error once you fix the first. When using comparison, you have to use “==” because otherwise GDScript thinks you’re trying to assign a value.