class_name Character extends CharacterBody2D const GRAVITY := 1200.0 @export var speed := 180.0 @export var jump_intensity := 304.056 @export var attack_duration := 0.4 @export var attack_lunge_duration := 0.18 @export var attack_lunge_speed := 220.0 @export var air_attack_duration := 0.45 @export var air_attack_lunge_duration := 0.22 @export var air_attack_lunge_speed := 260.0 @onready var visual: Node2D = $Visual @onready var animation_player: AnimationPlayer = $AnimationPlayer @onready var character_sprite: Sprite2D = $Visual/CharacterSprite const PRESENTATION_IDLE := &"idle" const PRESENTATION_WALK := &"walk" const PRESENTATION_JUMP := &"jump" const PRESENTATION_LAND := &"land" const PRESENTATION_ATTACK := &"attack" const PRESENTATION_AIR_ATTACK := &"air_attack" var anim_map := { PRESENTATION_IDLE: "idle", PRESENTATION_WALK: "idle", PRESENTATION_JUMP: "rising_slash", PRESENTATION_LAND: "idle", PRESENTATION_ATTACK: "atk_ground_1", PRESENTATION_AIR_ATTACK: "atk_air", } var attack_direction := Vector2.LEFT var attack_lunge_time_left := 0.0 var attack_time_left := 0.0 var heading := Vector2.LEFT var height := 0.0 var height_speed := 0.0 var state := PRESENTATION_IDLE func _physics_process(delta: float) -> void: handle_input() handle_air_time(delta) handle_attack_time(delta) handle_movement() handle_animations() set_sprite_height_position() set_heading() flip_sprites() move_and_slide() func _exit_tree() -> void: if animation_player != null: animation_player.stop() func handle_input() -> void: pass func handle_air_time(delta: float) -> void: if state != PRESENTATION_JUMP: return height += height_speed * delta if height <= 0.0 and height_speed < 0.0: height = 0.0 height_speed = 0.0 state = PRESENTATION_LAND else: height_speed -= GRAVITY * delta func handle_attack_time(delta: float) -> void: if state != PRESENTATION_ATTACK and state != PRESENTATION_AIR_ATTACK: return velocity.y = 0.0 attack_time_left -= delta if attack_time_left <= 0.0: state = PRESENTATION_IDLE velocity = Vector2.ZERO return attack_lunge_time_left -= delta if attack_lunge_time_left <= 0.0: velocity.x = 0.0 func handle_movement() -> void: if state == PRESENTATION_JUMP or state == PRESENTATION_ATTACK or state == PRESENTATION_AIR_ATTACK: return if state == PRESENTATION_LAND: state = PRESENTATION_IDLE elif absf(velocity.x) > 0.0: state = PRESENTATION_WALK else: state = PRESENTATION_IDLE func handle_animations() -> void: var animation_name: String = anim_map.get(state, "idle") if animation_player.has_animation(animation_name) and animation_player.current_animation != animation_name: animation_player.play(animation_name) func set_sprite_height_position() -> void: if visual != null: visual.position = Vector2.UP * height func set_heading() -> void: pass func flip_sprites() -> void: if visual == null: return var base_scale := absf(visual.scale.x) visual.scale.x = base_scale if heading == Vector2.LEFT else -base_scale func can_jump() -> bool: return state == PRESENTATION_IDLE or state == PRESENTATION_WALK func start_jump() -> void: state = PRESENTATION_JUMP height_speed = jump_intensity func begin_attack_motion(duration: float, next_velocity: Vector2) -> void: attack_lunge_time_left = maxf(0.0, duration) velocity = next_velocity func stop_attack_motion() -> void: attack_lunge_time_left = 0.0 velocity = Vector2.ZERO