class_name Player extends CharacterBody2D # Player States enum State { IDLE, RUN, JUMP, ATTACK_1, ATTACK_2, ATTACK_3, HEAVY_ATTACK, DASH, DASH_ATTACK, DEFEND, HURT, DEATH, } # Player Runtime Variables var direction: float = 0.0 var facing_direction: float = 1.0 var current_state: State = State.IDLE var is_attacking: bool = false var combo_step: int = 0 var combo_timer: float = 0.0 @onready var _sprite: AnimatedSprite2D = $AnimatedSprite2D # Player Exported Variables @export_group("Movement") @export var move_speed: float = 200.0 @export_group("Jump") @export var jump_velocity: float = -300.0 @export var gravity_scale: float = 1.0 @export_group("Combat") @export var attack_cooldown: float = 0.4 @export var heavy_attack_cooldown: float = 0.6 @export var combo_window: float = 0.6 @export var attack_move_speed: float = 0.0 @export_group("Dash") @export var dash_speed: float = 500.0 @export var dash_cooldown: float = 0.8 func _ready() -> void: _sprite.animation_finished.connect(_on_animation_finished) func _physics_process(delta: float) -> void: _apply_gravity(delta) _apply_movement(delta) _process_attack_input() _update_combo_timer(delta) _update_state() _update_animation() move_and_slide() func _apply_gravity(delta: float) -> void: if not is_on_floor(): velocity.y += ProjectSettings.get_setting("physics/2d/default_gravity") * gravity_scale * delta func _apply_movement(delta: float) -> void: if is_attacking: velocity.x = facing_direction * attack_move_speed return direction = Input.get_axis("move_left", "move_right") velocity.x = direction * move_speed if direction != 0.0: facing_direction = direction if is_on_floor() and Input.is_action_just_pressed("jump"): velocity.y = jump_velocity func _process_attack_input() -> void: if is_attacking or not Input.is_action_just_pressed("light_attack"): return if combo_step > 0 and combo_timer > 0.0: combo_step += 1 else: combo_step = 1 is_attacking = true combo_timer = 0.0 current_state = State.values()[State.ATTACK_1 + combo_step - 1] func _update_combo_timer(delta: float) -> void: if combo_timer > 0.0: combo_timer -= delta if combo_timer <= 0.0: combo_step = 0 func _on_animation_finished() -> void: if not is_attacking: return is_attacking = false if current_state == State.ATTACK_3: combo_step = 0 else: combo_timer = combo_window func _update_state() -> void: if is_attacking: return if not is_on_floor(): current_state = State.JUMP elif direction != 0.0: current_state = State.RUN else: current_state = State.IDLE func _update_animation() -> void: var animation_name: String = State.keys()[current_state].to_lower() if _sprite.animation != animation_name: _sprite.play(animation_name) _sprite.flip_h = facing_direction < 0.0