Files
Fighting_Rthythm_game/scenes/chart/chart_runner.gd
2026-07-02 09:47:52 -07:00

111 lines
2.9 KiB
GDScript

class_name ChartRunner
extends Node
signal chart_event_upcoming(event: Resource, time_to_event: float)
signal chart_event_triggered(event: Resource)
signal chart_reset(chart_id: StringName)
signal chart_finished(chart_id: StringName)
const UPCOMING_TIME_EPSILON := 0.02
@export var chart: Resource
@export var rhythm_manager_path: NodePath
@export var beat_time_override := 0.0
@export var auto_run := true
var running := true
var _upcoming_keys: Dictionary = {}
var _triggered_keys: Dictionary = {}
func _ready() -> void:
running = auto_run
func _physics_process(_delta: float) -> void:
if not running or chart == null:
return
var rhythm := _rhythm_manager()
if rhythm == null or not rhythm.has_method("song_position"):
return
update_for_song_time(float(rhythm.call("song_position")))
func set_chart(next_chart: Resource) -> void:
chart = next_chart
reset()
func reset() -> void:
_upcoming_keys.clear()
_triggered_keys.clear()
var chart_id := &""
if chart != null:
chart_id = StringName(str(chart.get("chart_id")))
chart_reset.emit(chart_id)
var bus := _event_bus_or_null()
if bus != null:
bus.emit_signal("chart_reset", chart_id)
func update_for_song_time(song_time: float) -> void:
if chart == null:
return
var beat_time := _beat_time()
for event: Resource in chart.call("all_events"):
var event_time := float(event.call("time_seconds", beat_time))
var time_to_event := event_time - song_time
var lead_time := maxf(0.0, float(event.get("lead_beats"))) * beat_time
var event_key: StringName = event.call("key")
if not _upcoming_keys.has(event_key) and time_to_event > 0.0 and time_to_event <= lead_time + UPCOMING_TIME_EPSILON:
_upcoming_keys[event_key] = true
_emit_upcoming(event, time_to_event)
if not _triggered_keys.has(event_key) and song_time >= event_time:
_triggered_keys[event_key] = true
_emit_triggered(event)
func pause() -> void:
running = false
func resume() -> void:
running = true
func _emit_upcoming(event: Resource, time_to_event: float) -> void:
chart_event_upcoming.emit(event, time_to_event)
var bus := _event_bus_or_null()
if bus != null:
bus.emit_signal("chart_event_upcoming", event, time_to_event)
func _emit_triggered(event: Resource) -> void:
chart_event_triggered.emit(event)
var bus := _event_bus_or_null()
if bus != null:
bus.emit_signal("chart_event_triggered", event)
func _beat_time() -> float:
if beat_time_override > 0.0:
return beat_time_override
var rhythm := _rhythm_manager()
if rhythm != null:
return float(rhythm.get("beat_time"))
return 0.5
func _rhythm_manager() -> Node:
if not is_inside_tree():
return null
if not rhythm_manager_path.is_empty():
return get_node_or_null(rhythm_manager_path)
return get_tree().root.get_node_or_null("RhythmManager")
func _event_bus_or_null() -> Node:
if not is_inside_tree():
return null
return get_tree().root.get_node_or_null("EventBus")