extends Node2D @onready var rhythm_conductor: Node = $RhythmConductor @onready var rhythm_track: Control = $RhythmFeedback/RhythmTrack @onready var rhythm_feedback_label: Label = $RhythmFeedback/JudgementLabel @onready var center_base: TextureRect = $RhythmFeedback/RhythmTrack/CenterBase @onready var center_flash: TextureRect = $RhythmFeedback/RhythmTrack/CenterFlash @onready var left_mover: TextureRect = $RhythmFeedback/RhythmTrack/LeftMover @onready var right_mover: TextureRect = $RhythmFeedback/RhythmTrack/RightMover var track_center := Vector2.ZERO var left_mover_start := Vector2.ZERO var right_mover_start := Vector2.ZERO var mover_size := Vector2.ZERO var center_flash_size := Vector2.ZERO var feedback_flash := 0.0 var beat_flash := 0.0 func _ready() -> void: _cache_rhythm_track_layout() rhythm_conductor.action_judged.connect(_on_rhythm_action_judged) rhythm_conductor.beat.connect(_on_rhythm_beat) rhythm_feedback_label.text = "READY" _update_rhythm_track(0.0) func _process(delta: float) -> void: _update_rhythm_track(delta) if feedback_flash > 0.0: feedback_flash = maxf(0.0, feedback_flash - delta * 4.0) rhythm_feedback_label.scale = Vector2.ONE * (1.0 + feedback_flash * 0.18) func _on_rhythm_action_judged(action_name: String, rating: Dictionary) -> void: var rating_name: String = str(rating.get("label", "miss")) var color: Color = rating.get("color", Color("ff0055")) as Color var diff: float = float(rating.get("diff", INF)) rhythm_feedback_label.text = "%s %s %s" % [ _format_action_name(action_name), rating_name.to_upper(), _format_signed_ms(diff), ] rhythm_feedback_label.modulate = color feedback_flash = 1.0 func _on_rhythm_beat(_position: int) -> void: beat_flash = 1.0 func _update_rhythm_track(delta: float) -> void: beat_flash = maxf(0.0, beat_flash - delta * 8.0) var progress := 0.0 if rhythm_conductor.has_method("get_current_beat_progress"): progress = float(rhythm_conductor.call("get_current_beat_progress")) if beat_flash > 0.15: progress = 1.0 _set_control_center(left_mover, left_mover_start.lerp(track_center, progress), mover_size) _set_control_center(right_mover, right_mover_start.lerp(track_center, progress), mover_size) _set_control_center(center_flash, track_center, center_flash_size) center_flash.modulate = Color(1.0, 1.0, 1.0, beat_flash) func _cache_rhythm_track_layout() -> void: track_center = _control_center(center_base) left_mover_start = _control_center(left_mover) right_mover_start = _control_center(right_mover) mover_size = left_mover.size center_flash_size = center_flash.size func _control_center(control: Control) -> Vector2: return Vector2( (control.offset_left + control.offset_right) * 0.5, (control.offset_top + control.offset_bottom) * 0.5 ) func _set_control_center(control: Control, center: Vector2, size: Vector2) -> void: control.offset_left = center.x - size.x * 0.5 control.offset_top = center.y - size.y * 0.5 control.offset_right = center.x + size.x * 0.5 control.offset_bottom = center.y + size.y * 0.5 func _format_action_name(action_name: String) -> String: match action_name: "left": return "LEFT" "right": return "RIGHT" "jump": return "JUMP" _: return action_name.to_upper() func _format_signed_ms(seconds: float) -> String: if is_inf(seconds): return "-- ms" return "%+.0f ms" % (seconds * 1000.0)