So I'm following a tutorial where they're using state machines to change states and I'm now working on an attack animation. Note that I'm not a very experienced programmer, still trying to learn.

The difference is that I'm using animatedsprite2D instead of the animation player. My problem is that I'm trying to reference a specific animation, but I have no idea how as it seems to be different between the two methods. If you wonder why animatedsprite2D, it's because I don't have that many animations and also the animations messed up for some reason when I moved them to the animation player/tree, but work on the animated sprites.

My code:

extends State

@export var return_state : State
@export var animated_attack : AnimatedSprite2D (not sure if this is even necessary)

func _on_animated_sprite_2d_2_animation_finished(anim_name):
	if(anim_name == "my animation"):
		next_state = return_state

This seems quite simple in the animation player, but how do I reference "if this thing equals this animation then change state" in an animated 2d sprite?

If you look at the AnimatedSprite2D class reference, you'll see it has the animation property which holds the name of the current animation.

In general, it's good to get into habit of skimming through reference pages of classes/objects you use. You can find a lot of answers that way, as well as discover new useful stuff.

    xyz
    I've actually been looking through that page and noticed there was a handy "get_animation" command, but I'm not sure how to use it.

    I thought I'd just connect it to my AnimatedSprite2D like: animated_attack.get_animation("fist"), but it starts giving an error saying "too many arguments for get_animation call. Expected at most 0 but received 1". I've been messing around with different things for several hours and tried to find examples on google, but after my options got exhausted I had to rely on the forums myself.

    • xyz replied to this.

      dumbfinntales get_animation() is just a getter method for the animation property. You can access the property directly or use a getter method. Either way it'll give you the name of the current animation. Passing any arguments to the getter method makes no sense.

        xyz
        I see, I think I get it now. This particular 2D sprite has only one animation. I'm doing my attack in a weird way as there are two separate sprites. One 2D sprite for the player itself, it contains the walk and jump animation. Also a falling animation. Then the attack is a separate fist sprite that's behind the player and once I press attack it flies forward.

        But I've tried three things: if(anim_name == "fist"), if(anim_name == animated_attack.get_animation()) and if(anim_name == animated_attack.animation) while they don't give errors, my character still doesn't want to return from the attack state back to ground state.

        • xyz replied to this.

          xyz
          Alright, the script in attack is very short as it's purpose is only to return back to ground state:

          extends State
          
          @export var return_state : State
          @export var animated_attack : AnimatedSprite2D
          
          func _on_animated_sprite_2d_2_animation_finished(anim_name):
          	if(anim_name == "fist"):
          		next_state = return_state

          Here's the ground state where you actually call the attack:

          extends State
          
          class_name GroundState
          
          @export var jump_velocity : float = -400.0
          @export var air_state : State
          @export var attack_state : State
          
          @export var animated_sprite : AnimatedSprite2D
          @export var animated_attack : AnimatedSprite2D
          
          func state_process(delta):
          	if(!character.is_on_floor()):
          		next_state = air_state
          		animated_sprite.play("fall_loop")
          
          func state_input(event : InputEvent):
          	if(event.is_action_pressed("jump")):
          		jump()
          	if(event.is_action_pressed("attack")):
          		attack()
          		
          func jump():
          	character.velocity.y = jump_velocity
          	next_state = air_state
          	animated_sprite.play("jump")
          	
          func attack():
          	next_state = attack_state
          	animated_attack.play("fist")

          And here below is a screenshot. It should have everything, if not I'll correct it

            dumbfinntales
            Just in case I'll also post the State and the state machine scripts too

            State:

            extends Node
            
            class_name State
            
            @export var can_move : bool = true
            
            var character : CharacterBody2D
            var next_state : State
            
            func state_process(delta):
            	pass
            
            func state_input(event : InputEvent):
            	pass
            
            func on_enter():
            	pass
            	
            func on_exit():
            	pass

            State machine:

            extends Node
            
            class_name CharacterStateMachine
            
            @export var current_state : State
            @export var character : CharacterBody2D
            
            var states : Array[State]
            
            func _ready():
            	for child in get_children():
            		if(child is State):
            			states.append(child)
            			
            			child.character = character
            		else:
            			push_warning("Child" + child.name + "is not a state for CharacterStateMachine")
            
            func _physics_process(delta):
            	if(current_state.next_state != null):
            		switch_states(current_state.next_state)
            		
            	current_state.state_process(delta)
            			
            func check_if_can_move():
            	return current_state.can_move
            	
            func switch_states(new_state : State):
            	if(current_state != null):
            		current_state.on_exit()
            		current_state.next_state = null
            		
            	current_state = new_state
            	current_state.on_enter()
            
            func _input(event : InputEvent):
            	current_state.state_input(event)

            Well looks like I managed to figure it out on my own! I just had to look up examples on how other people implemented attack animations, and boom got it working. I feel a bit ashamed how much trouble I had with something so simple, but guess that's how it is when you're starting out and barely understand programming.

            But I got it working by writing if(animated_attack.animation == "fist")