updated AudioManager to handle multiple sublayers
parent
96eac1c640
commit
ffe6c50e93
|
@ -0,0 +1,118 @@
|
|||
using Godot;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SupaLidlGame.Audio;
|
||||
|
||||
public sealed partial class AudioManager : Node
|
||||
{
|
||||
private ManagedAudioPlayer _ambientPlayer;
|
||||
|
||||
private List<ManagedAudioPlayer> _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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Plays ambient audio. Ambient audio will play alongside the current
|
||||
/// background audio and will replace the current ambient audio.
|
||||
/// </summary>
|
||||
public void PlayAmbient(AudioStream stream, float fade = 1)
|
||||
{
|
||||
if (IsPlayerValid(_ambientPlayer))
|
||||
{
|
||||
_ambientPlayer.FadeOut(fade, true);
|
||||
}
|
||||
_ambientPlayer = CreateAudioPlayer(stream);
|
||||
_ambientPlayer.Play();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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<AudioStreamPlayer> _players;
|
||||
|
||||
private Dictionary<Layer, AudioStreamPlayer> _players;
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
_players = new Dictionary<Layer, AudioStreamPlayer>();
|
||||
_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);
|
||||
}
|
||||
}
|
|
@ -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<AudioManager>("/root/AudioManager").PlayActive(boss.Music);
|
||||
GetNode<AudioManager>("/root/AudioManager").PlayBackground(boss.Music, 2);
|
||||
}
|
||||
|
||||
private void DeregisterBoss(Boss boss)
|
||||
{
|
||||
CurrentBoss = null;
|
||||
GetNode<AudioManager>("/root/AudioManager").StopActive();
|
||||
GetNode<AudioManager>("/root/AudioManager").StopBackground(2);
|
||||
}
|
||||
|
||||
private void LoadMap(Map map)
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
Loading…
Reference in New Issue