extends Node var music_player: AudioStreamPlayer var ambient_loop: AudioStreamPlayer var whale_player: AudioStreamPlayer var _whale_timer: Timer var _music_tween: Tween const MUSIC_PATH := "res://audio/music/" const SFX_PATH := "res://audio/sfx/" func _ready() -> void: music_player = AudioStreamPlayer.new() music_player.bus = "Music" music_player.volume_db = -10.0 add_child(music_player) ambient_loop = AudioStreamPlayer.new() ambient_loop.bus = "SFX" ambient_loop.volume_db = -12.0 add_child(ambient_loop) whale_player = AudioStreamPlayer.new() whale_player.bus = "SFX" whale_player.volume_db = -15.0 add_child(whale_player) _whale_timer = Timer.new() _whale_timer.one_shot = true _whale_timer.timeout.connect(_on_whale_timer) add_child(_whale_timer) _schedule_next_whale() func play_music(track_name: String) -> void: var path := MUSIC_PATH + track_name if not ResourceLoader.exists(path): return var stream: AudioStream = load(path) if stream == null: return music_player.stream = stream music_player.stream.loop = true music_player.volume_db = -40.0 music_player.play() if _music_tween: _music_tween.kill() _music_tween = create_tween() _music_tween.tween_property(music_player, "volume_db", -10.0, 3.0).set_trans(Tween.TRANS_SINE) func play_ambient_loop(loop_name: String) -> void: var path := SFX_PATH + loop_name if not ResourceLoader.exists(path): return var stream: AudioStream = load(path) if stream == null: return ambient_loop.stream = stream ambient_loop.stream.loop = true ambient_loop.play() func play_whale_call_random() -> void: var path := SFX_PATH + "whale_call.ogg" if not ResourceLoader.exists(path): return if whale_player.playing: return var stream: AudioStream = load(path) if stream == null: return whale_player.stream = stream whale_player.play() func play_bubble_sfx(position: Vector3) -> void: var path := SFX_PATH + "bubbles.ogg" if not ResourceLoader.exists(path): return var player := AudioStreamPlayer3D.new() player.bus = "SFX" player.volume_db = -8.0 player.max_distance = 20.0 player.attenuation_model = AudioStreamPlayer3D.ATTENUATION_INVERSE_SQUARE_DISTANCE add_child(player) player.global_position = position var stream: AudioStream = load(path) if stream == null: player.queue_free() return player.stream = stream player.play() player.finished.connect(player.queue_free) func set_music_volume(db: float) -> void: music_player.volume_db = db func set_sfx_volume(db: float) -> void: ambient_loop.volume_db = db whale_player.volume_db = db - 3.0 func _on_whale_timer() -> void: play_whale_call_random() _schedule_next_whale() func _schedule_next_whale() -> void: _whale_timer.wait_time = randf_range(30.0, 90.0) _whale_timer.start()