Combat System with Animation Player not working

Godot Version

Godot 4.5

Question

I am developing a top down RPG set during the 19th century Argentinian Civil Wars and managed to create states machines, but now I am stuck with the combat system. I followed a tutorial and dispite following it I can’t make it work. I have changed some things from the tutorial to fit my type of animation and maybe there is an issue there. This is the tutorial:https://www.youtube.com/watch?v=FszC2eTtbWA&list=PLS_-svNHQV8jbMK3UAMUOglpRDtRZ4-4r&index=5
I am using an animation player with separate sprites2D for the body parts and one for the weapon, so I can later set up a system to change weapon using textures. First time developing a game this complex and don’t know how and if it will work really. Anyways, the hitbox and hurtbox are not connecting. This is the Hit box script:

class_name Hitbox extends Area2D

@export var damage: int = 1

var has_hit: bool = false

func _ready() -> void:
	area_entered.connect(_on_hitbox_area_entered)

func reset_hit_status() -> void:
	has_hit = false
	
	
func _on_hitbox_area_entered(area: Area2D) -> void:
	if has_hit:
		return
	
	if area is Hurtbox and area.owner.has_method("take_damage"):
		has_hit = true
		area.owner.take_damage(damage)

This is the attack state script:

class_name AttackState extends State

func enter() → void:
GameManager.player.is_attacking = true
GameManager.player.can_attack = false
GameManager.player.velocity = Vector2.ZERO
GameManager.player.get_node(“Hitbox”).reset_hit_status()
GameManager.player.play_animation(“attack”)

func exit() → void:
GameManager.player.is_attacking = false
GameManager.player.can_attack = true

func physics_update(_delta: float) → void:
if not GameManager.player.animation_player.is_playing():
state_machine.change_state(“idle”)

The Player Script:

class_name Player extends CharacterBody2D

@onready var root_transform: Node2D = $Visual/RootTransform
@onready var animation_player: AnimationPlayer = $Visual/AnimationPlayer
@onready var state_machine: StateMachine = $StateMachine

@export var speed: float = 70.0
@export var acceleration: float = 800.0
@export var friction: float = 1000.0
@export var max_health: int = 10

var current_health: int = max_health
var last_direction := Vector2.RIGHT
var direction: Vector2 = Vector2.ZERO
var can_attack: bool = true
var is_attacking: bool = false

func _ready() → void:
GameManager.register_player(self)
animation_player.play(“idle”)

func _physics_process(_delta: float) → void:
direction= Input.get_vector(“ui_left”, “ui_right”, “ui_up”,“ui_down”)

if  direction.x  !=0:
	root_transform.scale.x =  -1 if  direction.x < 0  else 1
	
state_machine.physics_update(_delta)

move_and_slide()

func _unhandled_input(event: InputEvent) → void:
state_machine.handle_input(event)

func play_animation(animation_name: String) → void:
if animation_player.has_animation(animation_name):
animation_player.play(animation_name)

func take_damage(amount: int) → void:
current_health -= amount
if current_health <= 0:
print(“Character died”)
else:
if animation_player.has_animation(“hit”):
animation_player.play(“hit”)

The Enemy Script:

class_name Enemy extends CharacterBody2D

signal died

@onready var root_transform: Node2D = $Visual/Root_transform

@onready var animation_player: AnimationPlayer = $Visual/AnimationPlayer
@onready var state_machine: EnemyStateMachine = $StateMachine

@export_range(0, 100) var max_health: int = 3
@export_range(10, 200) var move_speed: float = 50.0

@export var knockback_force: float = 100.0

var is_knocked_back: bool = false

var current_health: int:
set(value):
current_health = clampi(value, 0, max_health)
if current_health <= 0:
die()

func _ready() → void:
current_health = max_health
print(current_health)

func _physics_process(delta: float) → void:
if state_machine.current_state:
state_machine.physics_update(delta)
move_and_slide()

func face_player() → void:
if not GameManager.player:
return

var to_player = GameManager.player.global_position - global_position

if to_player.x != 0:
	root_transform.scale.x = -1 if to_player.x < 0 else 1

func take_damage(amount: int) → void:
current_health -= amount
print("take damage, health: ", current_health)
apply_knockback()

func die() → void:
died.emit()
queue_free()

func play_animation(animation_name: String) → void:
if animation_player.has_animation(animation_name):
animation_player.play(animation_name)

func apply_knockback() → void:
if GameManager.player:
is_knocked_back = true

	var knockback_direction = (global_position - GameManager.player.global_position).normalized()
	velocity = knockback_direction * knockback_force
	
	await get_tree().create_timer(0.25).timeout
	velocity = Vector2.ZERO
	is_knocked_back = false

Never mind, the solutions was to properly activate and deactivate the hitbox inside the animation.

1 Like