diff --git a/Assets/Scripts/GameController.cs b/Assets/Scripts/GameController.cs index ad03fa5..8e9eba6 100644 --- a/Assets/Scripts/GameController.cs +++ b/Assets/Scripts/GameController.cs @@ -39,7 +39,7 @@ namespace Marro.PacManUdon private VRCObjectPool pelletPool; private Animator mazeSpriteAnimator; - private int pelletCount; + private int pelletCountTotal; private int pelletCountRemaining; private GameObject[] attractScreenElements; @@ -144,8 +144,8 @@ namespace Marro.PacManUdon if (Networking.IsOwner(gameObject)) { - pelletCount = pelletPool.Pool.Length; - pelletCountRemaining = pelletCount; + pelletCountTotal = pelletPool.Pool.Length; + pelletCountRemaining = pelletCountTotal; ghostManager.SetPelletsRemaining(pelletCountRemaining); ghostManager.NewLevel(); @@ -181,7 +181,9 @@ namespace Marro.PacManUdon soundManager.PlayPelletSound(); - int pelletsConsumed = pelletCount - pelletCountRemaining; + soundManager.UpdatePelletCount(pelletCountRemaining); + + int pelletsConsumed = pelletCountTotal - pelletCountRemaining; if (pelletCountRemaining <= 0) { StartTimeSequence(PacManTimeSequence.BoardClear); @@ -203,14 +205,14 @@ namespace Marro.PacManUdon AddScore(50); ghostManager.SetPowerPellet(true); pacMan.SetPowerPellet(true); - soundManager.StartGhostSound(true); + soundManager.SetGhostBlue(true); } public void EndPowerPellet() { ghostManager.SetPowerPellet(false); pacMan.SetPowerPellet(false); - soundManager.StartGhostSound(false); + soundManager.SetGhostBlue(false); } public void GotFruit() @@ -237,9 +239,14 @@ namespace Marro.PacManUdon StartTimeSequence(PacManTimeSequence.PacManCaught); } + public void NoGhostsScared() + { + soundManager.SetGhostBlue(false); + } + public void NoGhostsRetreating() { - soundManager.EndGhostRetreat(); + soundManager.SetGhostRetreat(false); } void BoardClearAnimation() @@ -1260,7 +1267,7 @@ namespace Marro.PacManUdon break; case 6: // Start game, end sequence - soundManager.StartGhostSound(false); + soundManager.StartGhostSound(); SetFrozen(false); break; } @@ -1337,7 +1344,7 @@ namespace Marro.PacManUdon case 4: // Unfreeze SetFrozen(false); - soundManager.StartGhostSound(false); + soundManager.StartGhostSound(); break; } } @@ -1357,7 +1364,7 @@ namespace Marro.PacManUdon SetPacManActive(true); SetFrozen(false); ghostManager.GhostCaughtContinue(); - soundManager.StartGhostRetreat(); + soundManager.SetGhostRetreat(true); break; } } @@ -1440,7 +1447,8 @@ namespace Marro.PacManUdon // Unfreeze SetFrozen(false); soundManager.SuppressSound(false); - soundManager.StartGhostSound(false); + soundManager.StartGhostSound(); + soundManager.UpdatePelletCount(pelletCountRemaining); break; } } diff --git a/Assets/Scripts/Ghost.cs b/Assets/Scripts/Ghost.cs index 8e9b6d2..2bef84f 100644 --- a/Assets/Scripts/Ghost.cs +++ b/Assets/Scripts/Ghost.cs @@ -144,6 +144,7 @@ namespace Marro.PacManUdon faceInStartingDirectionUntilUnfrozen = true; UpdateAnimator(); + RequestSerialization(); // animator.Play(0, -1, 0); // Debug.Log($"{gameObject} reset with state: {state}, target: {target}, offGrid: {offGrid}"); } @@ -768,6 +769,8 @@ namespace Marro.PacManUdon return ghostState; } + public bool IsScared => isScared; + public override Vector2 GetPosition() { return (Vector2)transform.localPosition; diff --git a/Assets/Scripts/GhostManager.cs b/Assets/Scripts/GhostManager.cs index a3e8ae0..215c05e 100644 --- a/Assets/Scripts/GhostManager.cs +++ b/Assets/Scripts/GhostManager.cs @@ -227,17 +227,33 @@ public void GhostReturned() { - Debug.Log("Ghost returned"); + bool noGhostsScared = true; + bool noGhostsRetreating = true; + foreach (var ghost in ghosts) { var state = ghost.GetGhostState(); + + if (ghost.IsScared) + { + noGhostsScared = false; + } + if (state == PacManGhostState.CaughtScore || state == PacManGhostState.Returning || state == PacManGhostState.Entering) { - return; + noGhostsRetreating = false; } } - gameController.NoGhostsRetreating(); + if (noGhostsScared) + { + gameController.NoGhostsScared(); + } + + if (noGhostsRetreating) + { + gameController.NoGhostsRetreating(); + } } void SetGhostBlinking(bool blinking) diff --git a/Assets/Scripts/SoundManager.cs b/Assets/Scripts/SoundManager.cs index b4e96ed..231d355 100644 --- a/Assets/Scripts/SoundManager.cs +++ b/Assets/Scripts/SoundManager.cs @@ -17,17 +17,24 @@ public class SoundManager : UdonSharpBehaviour [SerializeField] private AudioClip pacFruit; [SerializeField] private AudioClip pacCoin; [SerializeField] private AudioClip pacGhostEat; - [SerializeField] private AudioClip pacGhost1; [SerializeField] private AudioClip pacGhostBlue; [SerializeField] private AudioClip pacGhostRetreat; [SerializeField] private AudioClip pacExtraLife; + [SerializeField] private AudioClip siren0; + [SerializeField] private AudioClip siren1; + [SerializeField] private AudioClip siren2; + [SerializeField] private AudioClip siren3; + [SerializeField] private AudioClip siren4; + private AudioClip _nextDotSound; - private bool _isRetreating; - private bool _isBlue; + private bool _ghostRetreating; + private bool _ghostBlue; + private int _ghostSoundLevel; + private bool _currentlyPlayingSiren; private bool _suppress; - + public void Initialize() { Reset(); @@ -38,8 +45,12 @@ public class SoundManager : UdonSharpBehaviour StopAllSound(); _nextDotSound = pacDot2; - _isRetreating = false; - _isBlue = false; + + _ghostRetreating = false; + _ghostBlue = false; + _ghostSoundLevel = 0; + _currentlyPlayingSiren = false; + _suppress = true; } @@ -63,7 +74,7 @@ public class SoundManager : UdonSharpBehaviour PlaySound(audioSourcePacMan, _nextDotSound); _nextDotSound = _nextDotSound == pacDot1 ? pacDot2 : pacDot1; } - + public void PlayDeathSound() { PlaySound(audioSourcePacMan, pacDie1); @@ -89,40 +100,21 @@ public class SoundManager : UdonSharpBehaviour PlaySound(audioSourceExtraLife, pacExtraLife); } - public void StartGhostSound(bool isBlue) + public void StartGhostSound() { - Debug.Log($"Start ghost sound, isBlue: {isBlue}, _isRetreating: {_isRetreating}, _suppress: {_suppress}"); - - _isBlue = isBlue; - - if (_isRetreating) - { - // Retreating overrides other ghost sound - return; - } - - var sound = _isBlue ? pacGhostBlue : pacGhost1; - PlaySound(audioSourceGhosts, sound, true); + UpdateGhostSound(); } - public void StartGhostRetreat() + public void SetGhostBlue(bool isBlue) { - _isRetreating = true; - PlaySound(audioSourceGhosts, pacGhostRetreat, true); + _ghostBlue = isBlue; + UpdateGhostSound(); } - public void EndGhostRetreat() + public void SetGhostRetreat(bool isRetreating) { - Debug.Log("End ghost retreating"); - - if (!_isRetreating) - { - return; - } - - _isRetreating = false; - - StartGhostSound(_isBlue); + _ghostRetreating = isRetreating; + UpdateGhostSound(); } public void StopAllSound() @@ -132,6 +124,37 @@ public class SoundManager : UdonSharpBehaviour // audioSourceExtraLife is not stopped on purpose, this sound is never interrupted } + public void UpdatePelletCount(int pelletCount) + { + int level = 0; + if (pelletCount < 16) + { + level = 4; + } + else if (pelletCount < 32) + { + level = 3; + } + else if (pelletCount < 64) + { + level = 2; + } + else if (pelletCount < 220) + { + level = 1; + } + + Debug.Log($"UpdatePelletCount: {pelletCount}, level: {level}"); + + if (_ghostSoundLevel >= level) + { + return; + } + + _ghostSoundLevel = level; + UpdateGhostSound(); + } + private void PlaySound(AudioSource audioSource, AudioClip audioClip, bool loop = false) { // Debug.Log($"PlaySound, audioSource: {audioSource}, audioClip: {audioClip}, loop: {loop}, suppress: {_suppress}"); @@ -139,7 +162,7 @@ public class SoundManager : UdonSharpBehaviour { return; } - + if (loop && audioSource.clip == audioClip && audioSource.isPlaying) { // Don't restart a looping sound @@ -150,4 +173,76 @@ public class SoundManager : UdonSharpBehaviour audioSource.Play(); audioSource.loop = loop; } + + private void SwitchSound(AudioSource audioSource, AudioClip audioClip, bool loop) + { + if (_suppress) + { + return; + } + + if (audioSource.clip == audioClip) + { + // No need to switch + return; + } + + if (!audioSource.isPlaying || audioSource.clip == null) + { + PlaySound(audioSource, audioClip, loop); + } + + var newTimeSamples = (int)(audioSource.timeSamples / (double)audioSource.clip.samples * audioClip.samples); + + audioSource.clip = audioClip; + audioSource.timeSamples = newTimeSamples; + + audioSource.Play(); + } + + private void UpdateGhostSound() + { + if (_ghostRetreating) + { + PlaySound(audioSourceGhosts, pacGhostRetreat, true); + _currentlyPlayingSiren = false; + return; + } + + if (_ghostBlue) + { + PlaySound(audioSourceGhosts, pacGhostBlue, true); + _currentlyPlayingSiren = false; + return; + } + + var currentGhostLevelSound = GetSoundForGhostLevel(_ghostSoundLevel); + if (_currentlyPlayingSiren) + { + SwitchSound(audioSourceGhosts, currentGhostLevelSound, true); + } + else + { + PlaySound(audioSourceGhosts, currentGhostLevelSound, true); + } + + _currentlyPlayingSiren = true; + } + + private AudioClip GetSoundForGhostLevel(int ghostLevel) + { + switch (ghostLevel) + { + case 1: + return siren1; + case 2: + return siren2; + case 3: + return siren3; + case 4: + return siren4; + default: + return siren0; + }; + } } diff --git a/Assets/Sounds/siren0.wav b/Assets/Sounds/siren0.wav new file mode 100644 index 0000000..2ce8173 Binary files /dev/null and b/Assets/Sounds/siren0.wav differ diff --git a/Assets/Sounds/siren0.wav.meta b/Assets/Sounds/siren0.wav.meta new file mode 100644 index 0000000..d121450 --- /dev/null +++ b/Assets/Sounds/siren0.wav.meta @@ -0,0 +1,23 @@ +fileFormatVersion: 2 +guid: 6436dd8a1e10b744aaa22ec56d84b213 +AudioImporter: + externalObjects: {} + serializedVersion: 7 + defaultSettings: + serializedVersion: 2 + loadType: 0 + sampleRateSetting: 0 + sampleRateOverride: 44100 + compressionFormat: 1 + quality: 1 + conversionMode: 0 + preloadAudioData: 0 + platformSettingOverrides: {} + forceToMono: 0 + normalize: 1 + loadInBackground: 0 + ambisonic: 0 + 3D: 1 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Sounds/siren1.wav b/Assets/Sounds/siren1.wav new file mode 100644 index 0000000..926ce9b Binary files /dev/null and b/Assets/Sounds/siren1.wav differ diff --git a/Assets/Sounds/siren1.wav.meta b/Assets/Sounds/siren1.wav.meta new file mode 100644 index 0000000..9ef4ed9 --- /dev/null +++ b/Assets/Sounds/siren1.wav.meta @@ -0,0 +1,23 @@ +fileFormatVersion: 2 +guid: 47ab3d2cd7cb7c14d815192aac6200dd +AudioImporter: + externalObjects: {} + serializedVersion: 7 + defaultSettings: + serializedVersion: 2 + loadType: 0 + sampleRateSetting: 0 + sampleRateOverride: 44100 + compressionFormat: 1 + quality: 1 + conversionMode: 0 + preloadAudioData: 0 + platformSettingOverrides: {} + forceToMono: 0 + normalize: 1 + loadInBackground: 0 + ambisonic: 0 + 3D: 1 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Sounds/siren2.wav b/Assets/Sounds/siren2.wav new file mode 100644 index 0000000..2e7f933 Binary files /dev/null and b/Assets/Sounds/siren2.wav differ diff --git a/Assets/Sounds/siren2.wav.meta b/Assets/Sounds/siren2.wav.meta new file mode 100644 index 0000000..85c751d --- /dev/null +++ b/Assets/Sounds/siren2.wav.meta @@ -0,0 +1,23 @@ +fileFormatVersion: 2 +guid: c5d97d1fa09a0fd47b82e31cbcec1011 +AudioImporter: + externalObjects: {} + serializedVersion: 7 + defaultSettings: + serializedVersion: 2 + loadType: 0 + sampleRateSetting: 0 + sampleRateOverride: 44100 + compressionFormat: 1 + quality: 1 + conversionMode: 0 + preloadAudioData: 0 + platformSettingOverrides: {} + forceToMono: 0 + normalize: 1 + loadInBackground: 0 + ambisonic: 0 + 3D: 1 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Sounds/siren3.wav b/Assets/Sounds/siren3.wav new file mode 100644 index 0000000..f918c12 Binary files /dev/null and b/Assets/Sounds/siren3.wav differ diff --git a/Assets/Sounds/siren3.wav.meta b/Assets/Sounds/siren3.wav.meta new file mode 100644 index 0000000..fb3f3dc --- /dev/null +++ b/Assets/Sounds/siren3.wav.meta @@ -0,0 +1,23 @@ +fileFormatVersion: 2 +guid: 1838962b5d88adb438fb3249be103caf +AudioImporter: + externalObjects: {} + serializedVersion: 7 + defaultSettings: + serializedVersion: 2 + loadType: 0 + sampleRateSetting: 0 + sampleRateOverride: 44100 + compressionFormat: 1 + quality: 1 + conversionMode: 0 + preloadAudioData: 0 + platformSettingOverrides: {} + forceToMono: 0 + normalize: 1 + loadInBackground: 0 + ambisonic: 0 + 3D: 1 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Sounds/siren4.wav b/Assets/Sounds/siren4.wav new file mode 100644 index 0000000..3db307d Binary files /dev/null and b/Assets/Sounds/siren4.wav differ diff --git a/Assets/Sounds/siren4.wav.meta b/Assets/Sounds/siren4.wav.meta new file mode 100644 index 0000000..d052bac --- /dev/null +++ b/Assets/Sounds/siren4.wav.meta @@ -0,0 +1,23 @@ +fileFormatVersion: 2 +guid: 4a044a4155262b041a0b07392cd0f81b +AudioImporter: + externalObjects: {} + serializedVersion: 7 + defaultSettings: + serializedVersion: 2 + loadType: 0 + sampleRateSetting: 0 + sampleRateOverride: 44100 + compressionFormat: 1 + quality: 1 + conversionMode: 0 + preloadAudioData: 0 + platformSettingOverrides: {} + forceToMono: 0 + normalize: 1 + loadInBackground: 0 + ambisonic: 0 + 3D: 1 + userData: + assetBundleName: + assetBundleVariant: