Files
Fighting_Rthythm_game/scenes/components/charge_component.gd
2026-07-02 09:47:52 -07:00

127 lines
3.2 KiB
GDScript

class_name ChargeComponent
extends Node
signal charge_changed(current: float, maximum: float, charge_ready: bool, active: bool)
signal release_requested(skill_id: StringName, direction: Vector2)
@export var charge_duration := 1.1
@export var animation_player_path: NodePath
@export var effect_sprite_path: NodePath
var value := 0.0
var charge_ready := false
var active := false
var _hold_symbol: StringName = &""
var _hold_direction := Vector2.ZERO
var _effect_time := 0.0
var _animation_time := 0.0
@onready var _animation_player: AnimationPlayer = get_node_or_null(animation_player_path) as AnimationPlayer
@onready var _effect_sprite: Sprite2D = get_node_or_null(effect_sprite_path) as Sprite2D
func begin_hold(symbol: StringName, direction: Vector2) -> void:
_hold_symbol = symbol
_hold_direction = direction
func finish_hold(symbol: StringName) -> void:
if _hold_symbol != symbol:
return
var release_ready := active and charge_ready
var release_direction := _hold_direction
var release_skill := &"skill_a_charge_release" if symbol == &"A" else &"skill_d_charge_release"
cancel()
if release_ready:
release_requested.emit(release_skill, release_direction)
func tick(delta: float, can_charge: bool) -> void:
if _hold_symbol.is_empty():
return
if not active:
if not can_charge:
return
_start()
if not active:
return
_update_charge_animation(delta)
value = minf(charge_duration, value + delta)
charge_ready = value >= charge_duration
_update_charge_effect(delta)
_emit_changed()
func cancel() -> void:
_hold_symbol = &""
_hold_direction = Vector2.ZERO
active = false
value = 0.0
charge_ready = false
_animation_time = 0.0
_set_effect_visible(false)
_emit_changed()
func is_active() -> bool:
return active
func is_ready() -> bool:
return charge_ready
func maximum() -> float:
return charge_duration
func _start() -> void:
active = true
value = 0.0
charge_ready = false
_effect_time = 0.0
_animation_time = 0.0
_play_charge_animation(&"warrior_charge_intro")
_update_charge_effect(0.0)
_emit_changed()
func _update_charge_effect(delta: float) -> void:
if _effect_sprite == null:
return
_effect_sprite.visible = active
if not active:
return
_effect_time += delta
_effect_sprite.frame = int(_effect_time * 12.0) % 5
func _update_charge_animation(delta: float) -> void:
_animation_time += delta
var intro_length := _animation_length(&"warrior_charge_intro")
if _animation_time < intro_length:
_play_charge_animation(&"warrior_charge_intro")
else:
_play_charge_animation(&"warrior_charge_loop")
func _play_charge_animation(animation_name: StringName) -> void:
if _animation_player != null and _animation_player.has_animation(animation_name) and _animation_player.current_animation != animation_name:
_animation_player.play(animation_name)
func _animation_length(animation_name: StringName) -> float:
if _animation_player != null and _animation_player.has_animation(animation_name):
return maxf(0.1, _animation_player.get_animation(animation_name).length)
return 0.1
func _set_effect_visible(is_visible: bool) -> void:
if _effect_sprite != null:
_effect_sprite.visible = is_visible
func _emit_changed() -> void:
charge_changed.emit(value, charge_duration, charge_ready, active)