add initial project files and configurations, including EventBus, systems, and resources
This commit is contained in:
195
Code/Systems/SoundManager.cs
Normal file
195
Code/Systems/SoundManager.cs
Normal file
@@ -0,0 +1,195 @@
|
||||
using Godot;
|
||||
using MaxEffort.Code.Core;
|
||||
using MaxEffort.Code.Data;
|
||||
|
||||
namespace MaxEffort.Code.Systems;
|
||||
|
||||
[GlobalClass]
|
||||
public partial class SoundManager : Node
|
||||
{
|
||||
[Export] private SoundBank _bank;
|
||||
[Export] private int _poolSize = 8;
|
||||
|
||||
private AudioStreamPlayer[] _sfxPool;
|
||||
private AudioStreamPlayer _strainPlayer;
|
||||
private AudioStreamPlayer _heartbeatPlayer;
|
||||
private AudioStreamPlayer _musicPlayer;
|
||||
private bool _isLifting = false;
|
||||
private float _currentLiftProgress = 0f;
|
||||
|
||||
private int _masterBus;
|
||||
private int _musicBus;
|
||||
private int _sfxBus;
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
_masterBus = AudioServer.GetBusIndex("Master");
|
||||
_musicBus = AudioServer.GetBusIndex("Music");
|
||||
_sfxBus = AudioServer.GetBusIndex("Sfx");
|
||||
|
||||
InitializePool();
|
||||
|
||||
EventBus.OnLiftEffortApplied += HandleLiftEffort;
|
||||
EventBus.OnFocusRelease += HandleFocusRelease;
|
||||
EventBus.OnFocusChanged += OnFocusChanged;
|
||||
EventBus.OnLiftCompleted += HandleLiftComplete;
|
||||
EventBus.OnLiftProgress += OnLiftProgress;
|
||||
EventBus.OnHazardSpawned += OnOnHazardSpawned;
|
||||
EventBus.OnHazardResolved += OnHazardResolved;
|
||||
EventBus.OnCameraTrauma += OnCameraTrauma;
|
||||
|
||||
PlayMusic(_bank.GameMusic);
|
||||
}
|
||||
|
||||
public override void _ExitTree()
|
||||
{
|
||||
EventBus.OnLiftEffortApplied -= HandleLiftEffort;
|
||||
EventBus.OnFocusRelease -= HandleFocusRelease;
|
||||
EventBus.OnLiftCompleted -= HandleLiftComplete;
|
||||
EventBus.OnLiftProgress -= OnLiftProgress;
|
||||
EventBus.OnHazardSpawned -= OnOnHazardSpawned;
|
||||
EventBus.OnHazardResolved -= OnHazardResolved;
|
||||
EventBus.OnCameraTrauma -= OnCameraTrauma;
|
||||
}
|
||||
|
||||
public void PlayMusic(AudioStream clip)
|
||||
{
|
||||
if (clip == null || _musicPlayer.Stream == clip) return;
|
||||
_musicPlayer.Stream = clip;
|
||||
_musicPlayer.Play();
|
||||
}
|
||||
|
||||
public void ToggleMasterMute(bool isMuted)
|
||||
{
|
||||
AudioServer.SetBusMute(_masterBus, isMuted);
|
||||
}
|
||||
|
||||
public void ToggleMusicMute(bool isMuted)
|
||||
{
|
||||
AudioServer.SetBusMute(_musicBus, isMuted);
|
||||
}
|
||||
|
||||
private void InitializePool()
|
||||
{
|
||||
_sfxPool = new AudioStreamPlayer[_poolSize];
|
||||
for (var i = 0; i < _poolSize; i++)
|
||||
{
|
||||
var p = new AudioStreamPlayer();
|
||||
p.Bus = "Sfx";
|
||||
AddChild(p);
|
||||
_sfxPool[i] = p;
|
||||
}
|
||||
|
||||
_strainPlayer = new AudioStreamPlayer { Bus = "Sfx" };
|
||||
AddChild(_strainPlayer);
|
||||
|
||||
_heartbeatPlayer = new AudioStreamPlayer { Bus = "Sfx" };
|
||||
AddChild(_heartbeatPlayer);
|
||||
|
||||
_musicPlayer = new AudioStreamPlayer { Bus = "Music" };
|
||||
AddChild(_musicPlayer);
|
||||
|
||||
if (_bank != null && _bank.HeartbeatLoop != null)
|
||||
{
|
||||
_heartbeatPlayer.Stream = _bank.HeartbeatLoop;
|
||||
_heartbeatPlayer.VolumeDb = -80f;
|
||||
_heartbeatPlayer.Play();
|
||||
}
|
||||
}
|
||||
|
||||
private void PlaySfx(AudioStream clip, float pitch = 1.0f)
|
||||
{
|
||||
if (clip == null) return;
|
||||
|
||||
AudioStreamPlayer bestCandidate = null;
|
||||
var longestPlaybackPosition = -1f;
|
||||
|
||||
foreach (var player in _sfxPool)
|
||||
{
|
||||
if (!player.Playing)
|
||||
{
|
||||
bestCandidate = player;
|
||||
break;
|
||||
}
|
||||
|
||||
if (player.GetPlaybackPosition() > longestPlaybackPosition)
|
||||
{
|
||||
longestPlaybackPosition = player.GetPlaybackPosition();
|
||||
bestCandidate = player;
|
||||
}
|
||||
}
|
||||
|
||||
if (bestCandidate != null)
|
||||
{
|
||||
bestCandidate.Stream = clip;
|
||||
bestCandidate.PitchScale = pitch;
|
||||
bestCandidate.Play();
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleLiftEffort(float _)
|
||||
{
|
||||
if (!_isLifting)
|
||||
{
|
||||
_isLifting = true;
|
||||
if (_bank.StrainLoop != null)
|
||||
{
|
||||
_strainPlayer.Stream = _bank.StrainLoop;
|
||||
_strainPlayer.Play();
|
||||
}
|
||||
}
|
||||
|
||||
_strainPlayer.PitchScale = 1.0f + (_currentLiftProgress * 0.3f);
|
||||
}
|
||||
|
||||
private void HandleFocusRelease()
|
||||
{
|
||||
if (_isLifting)
|
||||
{
|
||||
_isLifting = false;
|
||||
_strainPlayer.Stop();
|
||||
PlaySfx(_bank.EffortExhale);
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleLiftComplete(bool success)
|
||||
{
|
||||
_strainPlayer.Stop();
|
||||
PlaySfx(success ? _bank.WinStinger : _bank.FailStinger);
|
||||
}
|
||||
|
||||
private void OnCameraTrauma(float amount)
|
||||
{
|
||||
if (amount > 0.5f) PlaySfx(_bank.CameraTrauma);
|
||||
}
|
||||
|
||||
private void OnHazardResolved(HazardType _)
|
||||
{
|
||||
PlaySfx(_bank.HazardClear);
|
||||
}
|
||||
|
||||
private void OnOnHazardSpawned(HazardType _)
|
||||
{
|
||||
PlaySfx(_bank.HazardSpawn);
|
||||
}
|
||||
|
||||
private void OnLiftProgress(float progress)
|
||||
{
|
||||
_currentLiftProgress = progress;
|
||||
}
|
||||
|
||||
private void OnFocusChanged(float focus)
|
||||
{
|
||||
if (focus < 0.1f)
|
||||
{
|
||||
_heartbeatPlayer.VolumeDb = -80f;
|
||||
}
|
||||
else
|
||||
{
|
||||
var t = (focus - 0.1f) / 0.9f;
|
||||
_heartbeatPlayer.VolumeDb = Mathf.Lerp(-30f, 5f, t);
|
||||
|
||||
_heartbeatPlayer.PitchScale = Mathf.Lerp(1.0f, 1.4f, t);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user