AnimationPlayer attack doesn't work with an animated sprite

Godot Version

4.3

Question

Hi! I’m trying to implement an attack animation into my game, and it doesn’t work. I know it has something to do with the physics process and how it works every second, and there is a lot of fixes for that. Still, I don’t understand how to implement them as I do movement animations with an Animated Sprite, and this particular attack with Animation Player, as I need collision shapes to be in the animation.
Is mixing those two a problem here?

When I press the attack button the animations technically plays - “ATTACK” is printed and the collision shape lights up for when the attack is supposed to hit, but the animation of the sprite itself shows up for just a split-second.
What should I do here?
I’d really appreciate your help.

extends CharacterBody2D


const SPEED = 130.0
var JUMP_VELOCITY = -360.0
const gravity = 1000
const fall_gravity = 1200

var is_wall_slide = false
var wall_jump_power = 300
const wall_slide_gravity = 50
var is_attacking = false
var is_flipped = false

@onready var animation_player = $AnimatedSprite2D/AnimationPlayer
@onready var animated_sprite = $AnimatedSprite2D
@onready var all_interactions = []
@onready var interactLabel = $"interaction/InteractLabel"


# Jump Curve
func apply_gravity(velocity :Vector2):
	if velocity.y < 0:
		return gravity
	else:
		return fall_gravity

func _physics_process(delta):
	
	# Interaction
	if Input.is_action_just_pressed("interact"):
		execute_interaction()
	
	if Input.is_action_just_pressed("attack"):
		attack()
	
	# Add the gravity.
	if not is_on_floor():
		velocity.y += apply_gravity(velocity) * delta
	
	# Handle jump.
	if Input.is_action_just_pressed("jump"): 
		if is_on_floor():
			velocity.y = JUMP_VELOCITY
		elif is_on_wall():
			velocity.y = JUMP_VELOCITY
			velocity.x = get_wall_normal().x * wall_jump_power
			
	# Release Jump
	if Input.is_action_just_released("jump") and velocity.y < 0:
		velocity.y = JUMP_VELOCITY / 4
		
	# Get the input direction: -1, 0, 1.
	var direction = Input.get_axis("move_left", "move_right")
	
	if direction:
		velocity.x = move_toward(velocity.x, direction * SPEED, 36.0)
	else:
		velocity.x = move_toward(velocity.x, 0, 36)

	move_and_slide()
	wall_slide(delta)
	attack()
	
	# Flip the spirte
	if direction > 0:
		animated_sprite.flip_h = false
		is_flipped = false
	elif direction < 0:
		animated_sprite.flip_h = true
		is_flipped = true
	# Play animation
	if is_on_floor():
		if Input.is_key_pressed(KEY_I):
			animated_sprite.play("idle_suit")
		else: if direction == 0:
			animated_sprite.play("idle")
		else:
			animated_sprite.play("run")
	else:
		animated_sprite.play("jump")
		
	if is_wall_slide:
		animated_sprite.play("wall_land_right")
		
	if is_attacking and !is_flipped:
		animation_player.play("attack_stab_right")
	elif is_attacking and is_flipped:
		animation_player.play("attack_stab_left")
	

func wall_slide(delta):
	# Wall Slide
	if is_on_wall() and !is_on_floor(): 
		if Input.is_action_pressed("move_left") or Input.is_action_pressed("move_right"):
			is_wall_slide = true
		else:
			is_wall_slide = false
	else:
		is_wall_slide = false
		
	if is_wall_slide:
		velocity.y += (wall_slide_gravity * delta)
		velocity.y = min(velocity.y, wall_slide_gravity)

func attack():
	if is_on_floor() and Input.is_action_just_pressed("attack"):
		is_attacking = true
		print("ATTACK")
	else:
		is_attacking = false
	

#interactions

func _on_area_2d_area_entered(area):
	all_interactions.insert(0, area)
	update_interactions()


func _on_area_2d_area_exited(area):
	all_interactions.erase(area)
	update_interactions()
	
func update_interactions():
	if all_interactions:
		interactLabel.text = all_interactions[0].interact_label
	else:
		interactLabel.text = ""

func execute_interaction():
	if all_interactions:
		var  cur_interaction = all_interactions[0]
		match  cur_interaction.interact_type:
			"swap_weapon": $Weapon.set_texture(load("res://assets/items/weapons/crossbow.png"))

Do you mean that the animation_player’s sprite configuration is overwritten by your general animated sprites?
if that is the case, then you need to disallow sprite adjustments while the animation is playing

	if animation_player.is_playing(): return

	# Flip the spirte
	if direction > 0:
		animated_sprite.flip_h = false
		is_flipped = false
	elif direction < 0:
		animated_sprite.flip_h = true
		is_flipped = true
	# Play animation
	if is_on_floor():
		if Input.is_key_pressed(KEY_I):
			animated_sprite.play("idle_suit")
		else: if direction == 0:
			animated_sprite.play("idle")
		else:
			animated_sprite.play("run")
	else:
		animated_sprite.play("jump")
		
	if is_wall_slide:
		animated_sprite.play("wall_land_right")
		
	if is_attacking and !is_flipped:
		animation_player.play("attack_stab_right")
	elif is_attacking and is_flipped:
		animation_player.play("attack_stab_left")
1 Like

That was totally it! Such a simple solution, tho I probably wouldn’t think about it. Thank you very much!

1 Like