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