Godot Version
4.2.2
Question
In the following code, I have used “await ap.animation_finished” when the enemy is in “ATTACK state” before player.take_damage(1) then change state to “MOVE state” to check the collision and if player.is_attacking.
However, it does not change state after enter the “ATTACK state” it continues to give (repeat?) player damage (func player.take_damage) even after player die()
player script:
@export var health = 40
var max_health = 4
func _ready():
health = max_health
add_to_group(“player”)
func take_damage(damage_amount):
if can_take_damage:
health -= damage_amount
if health <=0:
die()
if is_dead:
return
health -= amount
if health <= 0:
die()
func die():
if is_dead:
return
is_dead = true
velocity = Vector2.ZERO
ap.play("death")
queue_free()
code for enemy script:
extends CharacterBody2D
@onready var sprite = $Sprite2D
@onready var player = %Player
@onready var health = 20
@onready var rayCast = $RayCast2D
@onready var rayCast2 = $RayCast2D2
var move_direction
var wander_time : float
enum{
IDLE,
HURT,
ATTACK,
MOVE,
DEATH
}
var state = MOVE
@onready var ap = $AnimationPlayer
func _ready():
randomize_wander()
pass
func _physics_process(delta):
add_to_group(“enemy”)
match state:
IDLE:
ap.play("idle")
print("IDLE state")
HURT:
ap.play("hurt")
health -= 10
print("HURT! enemy health is ", health)
if health > 0:
state = MOVE
print("HURT to MOVE, health > 0")
else:
state = DEATH
print("HURT to DEATH, health <= 0")
**ATTACK: **
** ap.play(“attack”)**
** #player take damage after animation finish**
** await ap.animation_finished**
** player.take_damage(1)**
** print("ATTACK, player health is ", player.health)**
** #change state to MOVE to check ray cast collision**
** state = MOVE**
** print(“ATTACK to MOVE state”)**
MOVE:
ap.play("move")
if wander_time > 0:
wander_time -= delta
#change state to attack if player is colliding with rayCast (left and right)
if rayCast.is_colliding() or rayCast2.is_colliding():
# Get the collider object from the ray cast
var collider1 = rayCast.get_collider()
var collider2 = rayCast2.get_collider()
# Check if either collider is part of the "player" group
if (collider1 and collider1.is_in_group("player")) or (collider2 and collider2.is_in_group("player")):
print("player is collising with ray cast")
if player.is_attacking:
state = HURT
print("player is attaking, enemy MOVE to HURT state")
else:
state = ATTACK
print("player is not attacking, enemy MOVE to ATTACK state")
#move
velocity = move_direction * 50
move_and_slide()
randomize_wander()
DEATH:
ap.play("death") #in ap play "death", after animation_finished, will queue_free()
print("enemy DEATH")
func randomize_wander(): #randomize wander for MOVE state for x-axis (move left / right)
move_direction = Vector2(randf_range(-1, 1), 0).normalized()
wander_time = randf_range(1, 3)
if velocity.x < 0:
sprite.flip_h = false
else:
sprite.flip_h = true
pass
Output:
player is collising with ray cast
player is not attacking, enemy MOVE to ATTACK state
ATTACK, player health is 3
ATTACK to MOVE state
ATTACK, player health is 2
ATTACK to MOVE state
ATTACK, player health is 1
ATTACK to MOVE state
ATTACK, player health is 0
ATTACK to MOVE state
ATTACK, player health is -1
ATTACK to MOVE state
ATTACK, player health is -2