From ffe6c50e9350c97e467867c00670027ae3ceaaf6 Mon Sep 17 00:00:00 2001 From: HumanoidSandvichDispenser Date: Sat, 9 Sep 2023 15:14:53 -0700 Subject: [PATCH] updated AudioManager to handle multiple sublayers --- Audio/AudioManager.cs | 118 +++++++++++++++++++++++++ Audio/ManagedPlayer.cs | 45 ++++++++++ Utils/AudioManager.cs | 191 ----------------------------------------- Utils/World.cs | 5 +- project.godot | 2 +- 5 files changed, 167 insertions(+), 194 deletions(-) create mode 100644 Audio/AudioManager.cs create mode 100644 Audio/ManagedPlayer.cs delete mode 100644 Utils/AudioManager.cs diff --git a/Audio/AudioManager.cs b/Audio/AudioManager.cs new file mode 100644 index 0000000..5b4d00d --- /dev/null +++ b/Audio/AudioManager.cs @@ -0,0 +1,118 @@ +using Godot; +using System.Collections.Generic; + +namespace SupaLidlGame.Audio; + +public sealed partial class AudioManager : Node +{ + private ManagedAudioPlayer _ambientPlayer; + + private List _bgPlayers; + + public enum Layer + { + Ambient, + Background + } + + public AudioManager() + { + _bgPlayers = new(); + for (int i = 0; i < 4; i++) + { + _bgPlayers.Add(null); + } + } + + public ManagedAudioPlayer CreateAudioPlayer(AudioStream stream) + { + var player = new ManagedAudioPlayer(); + player.Stream = stream; + AddChild(player); + return player; + } + + /// + /// Plays ambient audio. Ambient audio will play alongside the current + /// background audio and will replace the current ambient audio. + /// + public void PlayAmbient(AudioStream stream, float fade = 1) + { + if (IsPlayerValid(_ambientPlayer)) + { + _ambientPlayer.FadeOut(fade, true); + } + _ambientPlayer = CreateAudioPlayer(stream); + _ambientPlayer.Play(); + } + + /// + /// Plays background audio. Background audio will play if no sublayer above + /// is playing, pause all sublayers below, and replace the current sublayer + /// if it is playing. + /// + public void PlayBackground(AudioStream stream, int sublayer = 0, float fade = 1) + { + // stop current sublayer if playing + if (IsPlayerValid(_bgPlayers[sublayer])) + { + _bgPlayers[sublayer].FadeOut(fade, true); + } + _bgPlayers[sublayer] = CreateAudioPlayer(stream); + + // pause all sublayers below this + for (int i = 0; i < sublayer; i++) + { + if (IsPlayerValid(_bgPlayers[i])) + { + if (!_bgPlayers[i].StreamPaused) + { + _bgPlayers[i]?.FadeOut(fade, pause: true); + } + } + } + + // if a sublayer above is not playing then play + if (!IsSublayerAboveValid(sublayer)) + { + _bgPlayers[sublayer].Play(); + } + } + + public void StopBackground(int sublayer, float fade = 1) + { + // kill current sublayer + _bgPlayers[sublayer]?.FadeOut(fade, true); + + // if sublayer above is not plyaing, play lowest sublayer + if (!IsSublayerAboveValid(sublayer)) + { + for (int i = sublayer - 1; i >= 0; i--) + { + if (IsPlayerValid(_bgPlayers[i])) + { + _bgPlayers[i].FadeIn(fade, unpause: true); + break; + } + } + } + } + + private bool IsSublayerAboveValid(int sublayer) + { + for (int i = sublayer + 1; i < 4; i++) + { + if (IsPlayerValid(_bgPlayers[i])) + { + return true; + } + } + + return false; + } + + private bool IsPlayerValid(ManagedAudioPlayer player) + { + return player is not null && IsInstanceValid(player) && !player.IsDead; + } +} diff --git a/Audio/ManagedPlayer.cs b/Audio/ManagedPlayer.cs new file mode 100644 index 0000000..7f55cb4 --- /dev/null +++ b/Audio/ManagedPlayer.cs @@ -0,0 +1,45 @@ +using Godot; + +namespace SupaLidlGame.Audio; + +public sealed partial class ManagedAudioPlayer : AudioStreamPlayer +{ + private Tween _tween; + + public bool IsDead { get; set; } + + private Tween GetNewTween() + { + if (_tween is not null && IsInstanceValid(_tween)) + { + _tween.Kill(); + } + + return _tween = GetTree().CreateTween().BindNode(this); + } + + public void FadeOut(float time, bool kill = false, bool pause = false) + { + GetNewTween(); + _tween.TweenProperty(this, "volume_db", -80, time); + if (kill) + { + IsDead = true; + _tween.TweenCallback(Callable.From(QueueFree)); + } + else if (pause) + { + _tween.TweenCallback(Callable.From(() => StreamPaused = true)); + } + } + + public void FadeIn(float time, bool unpause = false) + { + GetNewTween(); + _tween.TweenProperty(this, "volume_db", 0, time); + if (unpause) + { + _tween.TweenCallback(Callable.From(() => StreamPaused = false)); + } + } +} diff --git a/Utils/AudioManager.cs b/Utils/AudioManager.cs deleted file mode 100644 index 45b9185..0000000 --- a/Utils/AudioManager.cs +++ /dev/null @@ -1,191 +0,0 @@ -using Godot; -using System.Collections.Generic; - -namespace SupaLidlGame.Utils; - -public sealed partial class AudioManager : Node -{ - public enum Layer - { - Ambient, - BackgroundMusic, - ActiveMusic, - }; - - //private Array _players; - - private Dictionary _players; - - public override void _Ready() - { - _players = new Dictionary(); - _players.Add(Layer.Ambient, null); - _players.Add(Layer.BackgroundMusic, null); - _players.Add(Layer.ActiveMusic, null); - } - - public void PlayAmbient(AudioStream stream) - { - StopPlayback(Layer.Ambient); - _players[Layer.Ambient] = CreateAudioStreamPlayer(stream); - FadeIn(_players[Layer.Ambient]); - } - - public void PlayBackground(AudioStream stream) - { - StopPlayback(Layer.BackgroundMusic); - _players[Layer.BackgroundMusic] = CreateAudioStreamPlayer(stream); - if (!IsLayerValid(Layer.ActiveMusic)) - { - FadeIn(_players[Layer.BackgroundMusic]); - } - } - - public void StopBackground() - { - StopPlayback(Layer.BackgroundMusic); - } - - public void PlayActive(AudioStream stream) - { - _players[Layer.ActiveMusic] = CreateAudioStreamPlayer(stream); - _players[Layer.ActiveMusic].Play(); - if (IsLayerValid(Layer.BackgroundMusic)) - { - Pause(Layer.BackgroundMusic); - } - } - - public void StopActive() - { - StopPlayback(Layer.ActiveMusic); - if (IsLayerValid(Layer.BackgroundMusic)) - { - if (_players[Layer.BackgroundMusic].StreamPaused) - { - Unpause(Layer.BackgroundMusic); - } - else - { - _players[Layer.BackgroundMusic].Play(); - } - } - } - - public void Play(AudioStream stream, Layer layer) - { - switch (layer) - { - case Layer.Ambient: - PlayAmbient(stream); - break; - case Layer.BackgroundMusic: - PlayBackground(stream); - break; - case Layer.ActiveMusic: - PlayActive(stream); - break; - } - } - - public void Stop(Layer layer) - { - switch (layer) - { - case Layer.Ambient: - case Layer.BackgroundMusic: - StopPlayback(layer); - break; - case Layer.ActiveMusic: - StopActive(); - break; - } - } - - private void Pause(Layer layer) - { - var player = _players[layer]; - - if (player is null || !IsInstanceValid(player)) - { - return; - } - - FadeOut(player, pause: true); - } - - private void Unpause(Layer layer) - { - var player = _players[layer]; - - if (player is null || !IsInstanceValid(player)) - { - return; - } - - FadeIn(player, unpause: true); - } - - private void StopPlayback(Layer layer) - { - var player = _players[layer]; - - if (player is null || !IsInstanceValid(player)) - { - return; - } - - FadeOut(player, kill: true); - _players[layer] = null; - } - - private AudioStreamPlayer CreateAudioStreamPlayer(AudioStream stream) - { - var player = new AudioStreamPlayer(); - AddChild(player); - player.Stream = stream; - return player; - } - - private void FadeOut( - AudioStreamPlayer player, - double time = 1.0, - bool kill = false, - bool pause = false) - { - var tween = player.GetTree().CreateTween().BindNode(player); - tween.TweenProperty(player, "volume_db", 0, time); - if (kill) - { - tween.TweenCallback(Callable.From(player.QueueFree)); - } - else if (pause) - { - tween.TweenCallback( - Callable.From(() => player.StreamPaused = true)); - } - } - - private void FadeIn(AudioStreamPlayer player, - double time = 1.0, - bool unpause = false) - { - if (unpause) - { - player.StreamPaused = false; - } - else - { - player.Play(); - } - player.VolumeDb = 0; - var tween = player.GetTree().CreateTween().BindNode(player); - tween.TweenProperty(player, "volume_db", 1, time); - } - - public bool IsLayerValid(Layer layer) - { - var player = _players[layer]; - return player is not null && IsInstanceValid(player); - } -} diff --git a/Utils/World.cs b/Utils/World.cs index 614a7d0..237e494 100644 --- a/Utils/World.cs +++ b/Utils/World.cs @@ -1,4 +1,5 @@ using Godot; +using SupaLidlGame.Audio; using SupaLidlGame.Characters; using SupaLidlGame.Extensions; using SupaLidlGame.Scenes; @@ -123,13 +124,13 @@ public partial class World : Node return; } CurrentBoss = boss; - GetNode("/root/AudioManager").PlayActive(boss.Music); + GetNode("/root/AudioManager").PlayBackground(boss.Music, 2); } private void DeregisterBoss(Boss boss) { CurrentBoss = null; - GetNode("/root/AudioManager").StopActive(); + GetNode("/root/AudioManager").StopBackground(2); } private void LoadMap(Map map) diff --git a/project.godot b/project.godot index e687170..46e43de 100644 --- a/project.godot +++ b/project.godot @@ -22,7 +22,7 @@ GlobalState="*res://State/Global/GlobalState.cs" EventBus="*res://Events/EventBus.cs" BaseUI="*res://UI/Base.tscn" World="*res://Scenes/Level.tscn" -AudioManager="*res://Utils/AudioManager.cs" +AudioManager="*res://Audio/AudioManager.cs" DebugConsole="*res://Debug/DebugConsole.cs" Panku="*res://addons/panku_console/console.tscn"