Added more sound effeects. Added audio manager.
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using AlienAttack.MonoGame.GameLoops;
|
||||
using AlienAttack.MonoGame.Audio;
|
||||
using AlienAttack.MonoGame.GameLoops;
|
||||
using AlienAttack.MonoGame.View;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Audio;
|
||||
@@ -20,6 +21,7 @@ public class AlienAttackGame : Game
|
||||
|
||||
public SpriteBatch SpriteBatch => _spriteBatch;
|
||||
public ViewTransform ViewTransform => _viewTransform;
|
||||
public AudioManager Audio { get; private set; } = new();
|
||||
|
||||
private const string SDL = "SDL2.dll";
|
||||
|
||||
@@ -47,27 +49,7 @@ public class AlienAttackGame : Game
|
||||
|
||||
MaximizeWindow();
|
||||
|
||||
PlayBackgroundMusic();
|
||||
}
|
||||
|
||||
private void PlayBackgroundMusic()
|
||||
{
|
||||
Song song = Content.Load<Song>($@"Music\Untitled");
|
||||
|
||||
// Set whether the song should repeat when finished
|
||||
MediaPlayer.IsRepeating = true;
|
||||
|
||||
// Adjust the volume (0.0f to 1.0f)
|
||||
MediaPlayer.Volume = 0.5f;
|
||||
|
||||
// Check if the media player is already playing, if so, stop it
|
||||
if (MediaPlayer.State == MediaState.Playing)
|
||||
{
|
||||
MediaPlayer.Stop();
|
||||
}
|
||||
|
||||
// Start playing the background music
|
||||
MediaPlayer.Play(song);
|
||||
//Audio.PlayMusic(Content, @"Music\Untitled");
|
||||
}
|
||||
|
||||
private void ConfigureWindow()
|
||||
@@ -91,11 +73,16 @@ public class AlienAttackGame : Game
|
||||
{
|
||||
_spriteBatch = new SpriteBatch(GraphicsDevice);
|
||||
_gameLoop = new GameLoop(this);
|
||||
|
||||
// TODO: use this.Content to load your game content here
|
||||
Audio.LoadContent(Content);
|
||||
}
|
||||
|
||||
protected override void Update(GameTime gameTime)
|
||||
{
|
||||
if (IsActive == false)
|
||||
return;
|
||||
|
||||
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
|
||||
Exit();
|
||||
|
||||
|
||||
284
AlientAttack.MonoGame/Audio/AudioManager.cs
Normal file
284
AlientAttack.MonoGame/Audio/AudioManager.cs
Normal file
@@ -0,0 +1,284 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Audio;
|
||||
using Microsoft.Xna.Framework.Content;
|
||||
using Microsoft.Xna.Framework.Media;
|
||||
using System;
|
||||
|
||||
namespace AlienAttack.MonoGame.Audio;
|
||||
|
||||
public sealed class AudioManager
|
||||
{
|
||||
public float MasterVolume { get; set; } = 1f;
|
||||
public float SfxVolume { get; set; } = 0.8f;
|
||||
public float MusicVolume { get; set; } = 0.7f;
|
||||
|
||||
private readonly Random _random = new(12345);
|
||||
|
||||
// Pools
|
||||
private VariantSoundPool _playerGunPool = default!;
|
||||
private VariantSoundPool _enemyGunPool = default!;
|
||||
private VariantSoundPool _explosionPool = default!;
|
||||
private VariantSoundPool _impactPool = default!;
|
||||
|
||||
// Rate limiters (global caps per category/event)
|
||||
private RateLimiter _playerGunLimiter = new(0.06f); // max ~16 plays/sec
|
||||
private RateLimiter _enemyGunLimiter = new(0.12f); // max ~8 plays/sec (global for all enemies)
|
||||
private RateLimiter _impactLimiter = new(0.04f);
|
||||
|
||||
// Music
|
||||
private Song? _currentSong;
|
||||
private float _musicDuck = 1f; // 1.0 = normal, <1 = ducked
|
||||
private float _musicDuckTarget = 1f;
|
||||
private float _musicDuckSpeed = 6f; // how fast it moves toward target (bigger = snappier)
|
||||
|
||||
public void LoadContent(ContentManager content)
|
||||
{
|
||||
// Load SoundEffects once
|
||||
LoadPlayerGunPool(content);
|
||||
LoadEnemyGunPool(content);
|
||||
LoadImpactPool(content);
|
||||
LoadExplosionPool(content);
|
||||
|
||||
//var playerGun = content.Load<SoundEffect>("Audio/Sfx/player_fire");
|
||||
//var enemyGun = content.Load<SoundEffect>("Audio/Sfx/enemy_fire");
|
||||
//var explosion = content.Load<SoundEffect>("Audio/Sfx/explosion");
|
||||
//var impact = content.Load<SoundEffect>("Audio/Sfx/impact");
|
||||
|
||||
// Create pools with sane voice caps
|
||||
//_playerGunPool = new SoundPool(playerGun, maxVoices: 2);
|
||||
//_enemyGunPool = new SoundPool(enemyGun, maxVoices: 3);
|
||||
//_explosionPool = new SoundPool(explosion, maxVoices: 6);
|
||||
//_impactPool = new SoundPool(impact, maxVoices: 4);
|
||||
}
|
||||
|
||||
private void LoadPlayerGunPool(ContentManager content)
|
||||
{
|
||||
var playerGunVariants = new[]
|
||||
{
|
||||
content.Load<SoundEffect>("Sfx/GUNAuto_Assault Rifle A Fire_01_SFRMS_SCIWPNS"),
|
||||
content.Load<SoundEffect>("Sfx/GUNAuto_Assault Rifle A Fire_02_SFRMS_SCIWPNS"),
|
||||
content.Load<SoundEffect>("Sfx/GUNAuto_Assault Rifle A Fire_03_SFRMS_SCIWPNS"),
|
||||
content.Load<SoundEffect>("Sfx/GUNAuto_Assault Rifle A Fire_04_SFRMS_SCIWPNS"),
|
||||
content.Load<SoundEffect>("Sfx/GUNAuto_Assault Rifle A Fire_05_SFRMS_SCIWPNS"),
|
||||
content.Load<SoundEffect>("Sfx/GUNAuto_Assault Rifle A Fire_06_SFRMS_SCIWPNS")
|
||||
};
|
||||
|
||||
_playerGunPool = new VariantSoundPool(playerGunVariants, voicesPerVariant: 1, rng: _random);
|
||||
}
|
||||
|
||||
private void LoadEnemyGunPool(ContentManager content)
|
||||
{
|
||||
var variants = new[]
|
||||
{
|
||||
content.Load<SoundEffect>("Sfx/Pistol/GUNPis_Pistol Fire_01_SFRMS_SCIWPNS"),
|
||||
content.Load<SoundEffect>("Sfx/Pistol/GUNPis_Pistol Fire_02_SFRMS_SCIWPNS"),
|
||||
content.Load<SoundEffect>("Sfx/Pistol/GUNPis_Pistol Fire_03_SFRMS_SCIWPNS"),
|
||||
content.Load<SoundEffect>("Sfx/Pistol/GUNPis_Pistol Fire_04_SFRMS_SCIWPNS"),
|
||||
content.Load<SoundEffect>("Sfx/Pistol/GUNPis_Pistol Fire_05_SFRMS_SCIWPNS"),
|
||||
content.Load<SoundEffect>("Sfx/Pistol/GUNPis_Pistol Fire_06_SFRMS_SCIWPNS"),
|
||||
};
|
||||
|
||||
_enemyGunPool = new VariantSoundPool(variants, voicesPerVariant: 1, rng: _random);
|
||||
}
|
||||
|
||||
private void LoadImpactPool(ContentManager content)
|
||||
{
|
||||
var variants = new[]
|
||||
{
|
||||
content.Load<SoundEffect>("Sfx/Impact/BLLTImpt_Impact Object_01_SFRMS_SCIWPNS"),
|
||||
content.Load<SoundEffect>("Sfx/Impact/BLLTImpt_Impact Object_02_SFRMS_SCIWPNS"),
|
||||
content.Load<SoundEffect>("Sfx/Impact/BLLTImpt_Impact Object_03_SFRMS_SCIWPNS"),
|
||||
content.Load<SoundEffect>("Sfx/Impact/BLLTImpt_Impact Object_04_SFRMS_SCIWPNS"),
|
||||
content.Load<SoundEffect>("Sfx/Impact/BLLTImpt_Impact Object_05_SFRMS_SCIWPNS"),
|
||||
content.Load<SoundEffect>("Sfx/Impact/BLLTImpt_Impact Object_06_SFRMS_SCIWPNS"),
|
||||
};
|
||||
|
||||
_impactPool = new VariantSoundPool(variants, voicesPerVariant: 1, rng: _random);
|
||||
}
|
||||
|
||||
private void LoadExplosionPool(ContentManager content)
|
||||
{
|
||||
var variants = new[]
|
||||
{
|
||||
content.Load<SoundEffect>("Sfx/Explosions/EXPLDsgn_Explosion Impact_01_SFRMS_SCIWPNS"),
|
||||
content.Load<SoundEffect>("Sfx/Explosions/EXPLDsgn_Explosion Impact_02_SFRMS_SCIWPNS"),
|
||||
content.Load<SoundEffect>("Sfx/Explosions/EXPLDsgn_Explosion Impact_03_SFRMS_SCIWPNS"),
|
||||
content.Load<SoundEffect>("Sfx/Explosions/EXPLDsgn_Explosion Impact_04_SFRMS_SCIWPNS"),
|
||||
content.Load<SoundEffect>("Sfx/Explosions/EXPLDsgn_Explosion Impact_05_SFRMS_SCIWPNS"),
|
||||
content.Load<SoundEffect>("Sfx/Explosions/EXPLDsgn_Explosion Impact_06_SFRMS_SCIWPNS")
|
||||
};
|
||||
|
||||
_explosionPool = new VariantSoundPool(variants, voicesPerVariant: 1, rng: _random);
|
||||
}
|
||||
|
||||
// Call this once per frame
|
||||
public void Update(GameTime gameTime)
|
||||
{
|
||||
float dt = (float)gameTime.ElapsedGameTime.TotalSeconds;
|
||||
|
||||
_playerGunLimiter.Update(dt);
|
||||
_enemyGunLimiter.Update(dt);
|
||||
_impactLimiter.Update(dt);
|
||||
|
||||
// Smoothly approach the duck target
|
||||
_musicDuck = Approach(_musicDuck, _musicDuckTarget, _musicDuckSpeed * dt);
|
||||
|
||||
// Apply music volume
|
||||
MediaPlayer.Volume = Clamp01(MasterVolume * MusicVolume * _musicDuck);
|
||||
}
|
||||
|
||||
// -----------------------
|
||||
// Public SFX entry points
|
||||
// -----------------------
|
||||
|
||||
public void PlayPlayerFire()
|
||||
{
|
||||
if (!_playerGunLimiter.TryConsume()) return;
|
||||
|
||||
// Bullet sounds should be short + quiet-ish
|
||||
float baseVol = 0.35f;
|
||||
float vol = baseVol * RandRange(0.92f, 1.05f);
|
||||
float pitch = RandRange(-0.05f, 0.05f);
|
||||
|
||||
_playerGunPool.Play(
|
||||
volume: Clamp01(MasterVolume * SfxVolume * vol),
|
||||
pitch: pitch
|
||||
);
|
||||
}
|
||||
|
||||
public void PlayEnemyFire()
|
||||
{
|
||||
if (!_enemyGunLimiter.TryConsume()) return;
|
||||
|
||||
float baseVol = 0.28f;
|
||||
float vol = baseVol * RandRange(0.90f, 1.05f);
|
||||
float pitch = RandRange(-0.07f, 0.07f);
|
||||
|
||||
_enemyGunPool.Play(
|
||||
volume: Clamp01(MasterVolume * SfxVolume * vol),
|
||||
pitch: pitch
|
||||
);
|
||||
}
|
||||
|
||||
public void PlayImpact()
|
||||
{
|
||||
if (!_impactLimiter.TryConsume()) return;
|
||||
|
||||
float baseVol = 0.25f;
|
||||
float vol = baseVol * RandRange(0.90f, 1.10f);
|
||||
float pitch = RandRange(-0.08f, 0.08f);
|
||||
|
||||
_impactPool.Play(
|
||||
volume: Clamp01(MasterVolume * SfxVolume * vol),
|
||||
pitch: pitch
|
||||
);
|
||||
}
|
||||
|
||||
public void PlayExplosion(bool duckMusic = true)
|
||||
{
|
||||
float baseVol = 0.85f;
|
||||
float vol = baseVol * RandRange(0.95f, 1.05f);
|
||||
float pitch = RandRange(-0.04f, 0.04f);
|
||||
|
||||
_explosionPool.Play(
|
||||
volume: Clamp01(MasterVolume * SfxVolume * vol),
|
||||
pitch: pitch
|
||||
);
|
||||
|
||||
if (duckMusic)
|
||||
{
|
||||
// Duck music quickly, then let it recover
|
||||
DuckMusic(amount: 0.55f, holdSeconds: 0.20f, releaseSeconds: 0.35f);
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------
|
||||
// Music
|
||||
// -----------------------
|
||||
|
||||
public void PlayMusic(ContentManager content, string songAssetName, bool loop = true)
|
||||
{
|
||||
// Example asset name: "Audio/Music/level1"
|
||||
_currentSong = content.Load<Song>(songAssetName);
|
||||
|
||||
MediaPlayer.IsRepeating = loop;
|
||||
MediaPlayer.Volume = Clamp01(MasterVolume * MusicVolume * _musicDuck);
|
||||
MediaPlayer.Play(_currentSong);
|
||||
}
|
||||
|
||||
public void StopMusic() => MediaPlayer.Stop();
|
||||
public void PauseMusic() => MediaPlayer.Pause();
|
||||
public void ResumeMusic() => MediaPlayer.Resume();
|
||||
|
||||
// Duck helper: amount < 1.0 means quieter music (e.g., 0.55)
|
||||
public void DuckMusic(float amount, float holdSeconds, float releaseSeconds)
|
||||
{
|
||||
amount = Math.Clamp(amount, 0.05f, 1f);
|
||||
_musicDuckTarget = amount;
|
||||
|
||||
// Use a tiny internal timer without introducing a scheduler:
|
||||
// We'll set a one-shot "return to 1" using a lightweight countdown.
|
||||
_duckReturnTimer = holdSeconds;
|
||||
_duckReleaseSeconds = Math.Max(0.01f, releaseSeconds);
|
||||
}
|
||||
|
||||
private float _duckReturnTimer = 0f;
|
||||
private float _duckReleaseSeconds = 0.35f;
|
||||
|
||||
// Call from Update to manage duck release
|
||||
private void HandleDuckRelease(float dt)
|
||||
{
|
||||
if (_musicDuckTarget < 1f)
|
||||
{
|
||||
_duckReturnTimer -= dt;
|
||||
if (_duckReturnTimer <= 0f)
|
||||
{
|
||||
// start releasing
|
||||
_musicDuckTarget = 1f;
|
||||
_musicDuckSpeed = 1f / _duckReleaseSeconds; // approx
|
||||
// after it reaches 1, you can restore default speed if you want
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// restore default “snappiness” once fully normal
|
||||
if (Math.Abs(_musicDuck - 1f) < 0.001f)
|
||||
_musicDuckSpeed = 6f;
|
||||
}
|
||||
}
|
||||
|
||||
// Update override to include duck release handling
|
||||
public void UpdateWithDuck(GameTime gameTime)
|
||||
{
|
||||
float dt = (float)gameTime.ElapsedGameTime.TotalSeconds;
|
||||
|
||||
_playerGunLimiter.Update(dt);
|
||||
_enemyGunLimiter.Update(dt);
|
||||
_impactLimiter.Update(dt);
|
||||
|
||||
HandleDuckRelease(dt);
|
||||
|
||||
_musicDuck = Approach(_musicDuck, _musicDuckTarget, _musicDuckSpeed * dt);
|
||||
MediaPlayer.Volume = Clamp01(MasterVolume * MusicVolume * _musicDuck);
|
||||
}
|
||||
|
||||
// -----------------------
|
||||
// Utilities
|
||||
// -----------------------
|
||||
|
||||
private float RandRange(float min, float max)
|
||||
=> (float)(min + _random.NextDouble() * (max - min));
|
||||
|
||||
private static float Clamp01(float v) => Math.Clamp(v, 0f, 1f);
|
||||
|
||||
private static float Approach(float current, float target, float maxDelta)
|
||||
{
|
||||
if (current < target)
|
||||
return Math.Min(current + maxDelta, target);
|
||||
|
||||
if (current > target)
|
||||
return Math.Max(current - maxDelta, target);
|
||||
|
||||
return current;
|
||||
}
|
||||
}
|
||||
25
AlientAttack.MonoGame/Audio/RateLimiter.cs
Normal file
25
AlientAttack.MonoGame/Audio/RateLimiter.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
namespace AlienAttack.MonoGame.Audio;
|
||||
|
||||
public sealed class RateLimiter(float cooldownSeconds)
|
||||
{
|
||||
private readonly float _cooldownSeconds = cooldownSeconds <= 0 ? 0.0001f : cooldownSeconds;
|
||||
private float _timer = 0f;
|
||||
|
||||
public void Update(float deltaTime)
|
||||
{
|
||||
_timer -= deltaTime;
|
||||
|
||||
if (_timer < 0f)
|
||||
_timer = 0f;
|
||||
}
|
||||
|
||||
public bool TryConsume()
|
||||
{
|
||||
if (_timer > 0f)
|
||||
return false;
|
||||
|
||||
_timer = _cooldownSeconds;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
37
AlientAttack.MonoGame/Audio/SoundPool.cs
Normal file
37
AlientAttack.MonoGame/Audio/SoundPool.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using Microsoft.Xna.Framework.Audio;
|
||||
using System;
|
||||
|
||||
namespace AlienAttack.MonoGame.Audio;
|
||||
|
||||
public sealed class SoundPool
|
||||
{
|
||||
private readonly SoundEffectInstance[] _voices;
|
||||
private int _cursor;
|
||||
|
||||
public SoundPool(SoundEffect effect, int maxVoices)
|
||||
{
|
||||
ArgumentOutOfRangeException.ThrowIfLessThan(maxVoices, 1);
|
||||
|
||||
_voices = new SoundEffectInstance[maxVoices];
|
||||
|
||||
for (int i = 0; i < maxVoices; i++)
|
||||
_voices[i] = effect.CreateInstance();
|
||||
}
|
||||
|
||||
public void Play(float volume = 1f, float pitch = 0f, float pan = 0f)
|
||||
{
|
||||
SoundEffectInstance instance = _voices[_cursor];
|
||||
|
||||
_cursor = (_cursor + 1) % _voices.Length;
|
||||
|
||||
// "Voice stealing": stop if currently playing, then reuse immediately
|
||||
if (instance.State == SoundState.Playing)
|
||||
instance.Stop();
|
||||
|
||||
instance.Volume = Math.Clamp(volume, 0f, 1f);
|
||||
instance.Pitch = Math.Clamp(pitch, -1f, 1f);
|
||||
instance.Pan = Math.Clamp(pan, -1f, 1f);
|
||||
|
||||
instance.Play();
|
||||
}
|
||||
}
|
||||
48
AlientAttack.MonoGame/Audio/VariantSoundPool.cs
Normal file
48
AlientAttack.MonoGame/Audio/VariantSoundPool.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
using Microsoft.Xna.Framework.Audio;
|
||||
using System;
|
||||
|
||||
namespace AlienAttack.MonoGame.Audio;
|
||||
|
||||
public sealed class VariantSoundPool
|
||||
{
|
||||
private readonly SoundPool[] _variantPools;
|
||||
private readonly Random _rng;
|
||||
private int _lastIndex = -1;
|
||||
|
||||
public VariantSoundPool(SoundEffect[] variants, int voicesPerVariant, Random rng)
|
||||
{
|
||||
if (variants == null || variants.Length == 0)
|
||||
throw new ArgumentException("At least one variant is required.", nameof(variants));
|
||||
|
||||
ArgumentOutOfRangeException.ThrowIfLessThan(voicesPerVariant, 1);
|
||||
|
||||
_rng = rng ?? throw new ArgumentNullException(nameof(rng));
|
||||
|
||||
_variantPools = new SoundPool[variants.Length];
|
||||
|
||||
for (int i = 0; i < variants.Length; i++)
|
||||
_variantPools[i] = new SoundPool(variants[i], voicesPerVariant);
|
||||
}
|
||||
|
||||
public void Play(float volume = 1f, float pitch = 0f, float pan = 0f, bool avoidImmediateRepeat = true)
|
||||
{
|
||||
int idx = PickVariantIndex(avoidImmediateRepeat);
|
||||
_variantPools[idx].Play(volume, pitch, pan);
|
||||
}
|
||||
|
||||
private int PickVariantIndex(bool avoidImmediateRepeat)
|
||||
{
|
||||
if (_variantPools.Length == 1)
|
||||
return 0;
|
||||
|
||||
int idx = _rng.Next(_variantPools.Length);
|
||||
if (!avoidImmediateRepeat) { _lastIndex = idx; return idx; }
|
||||
|
||||
// Avoid playing the exact same sample twice in a row (nice polish)
|
||||
if (idx == _lastIndex)
|
||||
idx = (idx + 1 + _rng.Next(_variantPools.Length - 1)) % _variantPools.Length;
|
||||
|
||||
_lastIndex = idx;
|
||||
return idx;
|
||||
}
|
||||
}
|
||||
@@ -151,6 +151,78 @@
|
||||
/processorParam:Quality=Best
|
||||
/build:Sfx/GUNPis_Pistol Fire_06_SFRMS_SCIWPNS.wav
|
||||
|
||||
#begin Sfx/Impact/BLLTImpt_Impact Object_01_SFRMS_SCIWPNS.wav
|
||||
/importer:WavImporter
|
||||
/processor:SoundEffectProcessor
|
||||
/processorParam:Quality=Best
|
||||
/build:Sfx/Impact/BLLTImpt_Impact Object_01_SFRMS_SCIWPNS.wav;Sfx/Impact/BLLTImpt_Impact Object_01_SFRMS_SCIWPNS
|
||||
|
||||
#begin Sfx/Impact/BLLTImpt_Impact Object_02_SFRMS_SCIWPNS.wav
|
||||
/importer:WavImporter
|
||||
/processor:SoundEffectProcessor
|
||||
/processorParam:Quality=Best
|
||||
/build:Sfx/Impact/BLLTImpt_Impact Object_02_SFRMS_SCIWPNS.wav;Sfx/Impact/BLLTImpt_Impact Object_02_SFRMS_SCIWPNS
|
||||
|
||||
#begin Sfx/Impact/BLLTImpt_Impact Object_03_SFRMS_SCIWPNS.wav
|
||||
/importer:WavImporter
|
||||
/processor:SoundEffectProcessor
|
||||
/processorParam:Quality=Best
|
||||
/build:Sfx/Impact/BLLTImpt_Impact Object_03_SFRMS_SCIWPNS.wav;Sfx/Impact/BLLTImpt_Impact Object_03_SFRMS_SCIWPNS
|
||||
|
||||
#begin Sfx/Impact/BLLTImpt_Impact Object_04_SFRMS_SCIWPNS.wav
|
||||
/importer:WavImporter
|
||||
/processor:SoundEffectProcessor
|
||||
/processorParam:Quality=Best
|
||||
/build:Sfx/Impact/BLLTImpt_Impact Object_04_SFRMS_SCIWPNS.wav;Sfx/Impact/BLLTImpt_Impact Object_04_SFRMS_SCIWPNS
|
||||
|
||||
#begin Sfx/Impact/BLLTImpt_Impact Object_05_SFRMS_SCIWPNS.wav
|
||||
/importer:WavImporter
|
||||
/processor:SoundEffectProcessor
|
||||
/processorParam:Quality=Best
|
||||
/build:Sfx/Impact/BLLTImpt_Impact Object_05_SFRMS_SCIWPNS.wav;Sfx/Impact/BLLTImpt_Impact Object_05_SFRMS_SCIWPNS
|
||||
|
||||
#begin Sfx/Impact/BLLTImpt_Impact Object_06_SFRMS_SCIWPNS.wav
|
||||
/importer:WavImporter
|
||||
/processor:SoundEffectProcessor
|
||||
/processorParam:Quality=Best
|
||||
/build:Sfx/Impact/BLLTImpt_Impact Object_06_SFRMS_SCIWPNS.wav;Sfx/Impact/BLLTImpt_Impact Object_06_SFRMS_SCIWPNS
|
||||
|
||||
#begin Sfx/Pistol/GUNPis_Pistol Fire_01_SFRMS_SCIWPNS.wav
|
||||
/importer:WavImporter
|
||||
/processor:SoundEffectProcessor
|
||||
/processorParam:Quality=Best
|
||||
/build:Sfx/Pistol/GUNPis_Pistol Fire_01_SFRMS_SCIWPNS.wav;Sfx/Pistol/GUNPis_Pistol Fire_01_SFRMS_SCIWPNS
|
||||
|
||||
#begin Sfx/Pistol/GUNPis_Pistol Fire_02_SFRMS_SCIWPNS.wav
|
||||
/importer:WavImporter
|
||||
/processor:SoundEffectProcessor
|
||||
/processorParam:Quality=Best
|
||||
/build:Sfx/Pistol/GUNPis_Pistol Fire_02_SFRMS_SCIWPNS.wav;Sfx/Pistol/GUNPis_Pistol Fire_02_SFRMS_SCIWPNS
|
||||
|
||||
#begin Sfx/Pistol/GUNPis_Pistol Fire_03_SFRMS_SCIWPNS.wav
|
||||
/importer:WavImporter
|
||||
/processor:SoundEffectProcessor
|
||||
/processorParam:Quality=Best
|
||||
/build:Sfx/Pistol/GUNPis_Pistol Fire_03_SFRMS_SCIWPNS.wav;Sfx/Pistol/GUNPis_Pistol Fire_03_SFRMS_SCIWPNS
|
||||
|
||||
#begin Sfx/Pistol/GUNPis_Pistol Fire_04_SFRMS_SCIWPNS.wav
|
||||
/importer:WavImporter
|
||||
/processor:SoundEffectProcessor
|
||||
/processorParam:Quality=Best
|
||||
/build:Sfx/Pistol/GUNPis_Pistol Fire_04_SFRMS_SCIWPNS.wav;Sfx/Pistol/GUNPis_Pistol Fire_04_SFRMS_SCIWPNS
|
||||
|
||||
#begin Sfx/Pistol/GUNPis_Pistol Fire_05_SFRMS_SCIWPNS.wav
|
||||
/importer:WavImporter
|
||||
/processor:SoundEffectProcessor
|
||||
/processorParam:Quality=Best
|
||||
/build:Sfx/Pistol/GUNPis_Pistol Fire_05_SFRMS_SCIWPNS.wav;Sfx/Pistol/GUNPis_Pistol Fire_05_SFRMS_SCIWPNS
|
||||
|
||||
#begin Sfx/Pistol/GUNPis_Pistol Fire_06_SFRMS_SCIWPNS.wav
|
||||
/importer:WavImporter
|
||||
/processor:SoundEffectProcessor
|
||||
/processorParam:Quality=Best
|
||||
/build:Sfx/Pistol/GUNPis_Pistol Fire_06_SFRMS_SCIWPNS.wav;Sfx/Pistol/GUNPis_Pistol Fire_06_SFRMS_SCIWPNS
|
||||
|
||||
#begin Sfx/Shield/SCIEnrg_Shield Activate_01_SFRMS_SCIWPNS.wav
|
||||
/importer:WavImporter
|
||||
/processor:SoundEffectProcessor
|
||||
@@ -181,6 +253,42 @@
|
||||
/processorParam:Quality=Best
|
||||
/build:Sfx/Shield/SCIEnrg_Shield Activate_05_SFRMS_SCIWPNS.wav;Sfx/Shield/SCIEnrg_Shield Activate_05_SFRMS_SCIWPNS
|
||||
|
||||
#begin Sfx/Silenced Pistol/GUNSupr_Silenced Pistol Fire Short_01_SFRMS_SCIWPNS.wav
|
||||
/importer:WavImporter
|
||||
/processor:SoundEffectProcessor
|
||||
/processorParam:Quality=Best
|
||||
/build:Sfx/Silenced Pistol/GUNSupr_Silenced Pistol Fire Short_01_SFRMS_SCIWPNS.wav;Sfx/Silenced Pistol/GUNSupr_Silenced Pistol Fire Short_01_SFRMS_SCIWPNS
|
||||
|
||||
#begin Sfx/Silenced Pistol/GUNSupr_Silenced Pistol Fire Short_02_SFRMS_SCIWPNS.wav
|
||||
/importer:WavImporter
|
||||
/processor:SoundEffectProcessor
|
||||
/processorParam:Quality=Best
|
||||
/build:Sfx/Silenced Pistol/GUNSupr_Silenced Pistol Fire Short_02_SFRMS_SCIWPNS.wav;Sfx/Silenced Pistol/GUNSupr_Silenced Pistol Fire Short_02_SFRMS_SCIWPNS
|
||||
|
||||
#begin Sfx/Silenced Pistol/GUNSupr_Silenced Pistol Fire Short_03_SFRMS_SCIWPNS.wav
|
||||
/importer:WavImporter
|
||||
/processor:SoundEffectProcessor
|
||||
/processorParam:Quality=Best
|
||||
/build:Sfx/Silenced Pistol/GUNSupr_Silenced Pistol Fire Short_03_SFRMS_SCIWPNS.wav;Sfx/Silenced Pistol/GUNSupr_Silenced Pistol Fire Short_03_SFRMS_SCIWPNS
|
||||
|
||||
#begin Sfx/Silenced Pistol/GUNSupr_Silenced Pistol Fire Short_04_SFRMS_SCIWPNS.wav
|
||||
/importer:WavImporter
|
||||
/processor:SoundEffectProcessor
|
||||
/processorParam:Quality=Best
|
||||
/build:Sfx/Silenced Pistol/GUNSupr_Silenced Pistol Fire Short_04_SFRMS_SCIWPNS.wav;Sfx/Silenced Pistol/GUNSupr_Silenced Pistol Fire Short_04_SFRMS_SCIWPNS
|
||||
|
||||
#begin Sfx/Silenced Pistol/GUNSupr_Silenced Pistol Fire Short_05_SFRMS_SCIWPNS.wav
|
||||
/importer:WavImporter
|
||||
/processor:SoundEffectProcessor
|
||||
/processorParam:Quality=Best
|
||||
/build:Sfx/Silenced Pistol/GUNSupr_Silenced Pistol Fire Short_05_SFRMS_SCIWPNS.wav;Sfx/Silenced Pistol/GUNSupr_Silenced Pistol Fire Short_05_SFRMS_SCIWPNS
|
||||
|
||||
#begin Sfx/Silenced Pistol/GUNSupr_Silenced Pistol Fire Short_06_SFRMS_SCIWPNS.wav
|
||||
/importer:WavImporter
|
||||
/processor:SoundEffectProcessor
|
||||
/processorParam:Quality=Best
|
||||
/build:Sfx/Silenced Pistol/GUNSupr_Silenced Pistol Fire Short_06_SFRMS_SCIWPNS.wav;Sfx/Silenced Pistol/GUNSupr_Silenced Pistol Fire Short_06_SFRMS_SCIWPNS
|
||||
|
||||
#begin Sprites/Asteroid 01_png_processed.png
|
||||
/importer:TextureImporter
|
||||
/processor:TextureProcessor
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,4 +1,5 @@
|
||||
using AlienAttack.MonoGame.View;
|
||||
using AlienAttack.MonoGame.Audio;
|
||||
using AlienAttack.MonoGame.View;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Content;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
@@ -11,6 +12,7 @@ internal abstract class GameLoopBase(AlienAttackGame game) : IGameLoop
|
||||
protected readonly ContentManager Content = game.Content;
|
||||
protected readonly SpriteBatch SpriteBatch = game.SpriteBatch;
|
||||
protected readonly ViewTransform ViewTransform = game.ViewTransform;
|
||||
protected readonly AudioManager Audio = game.Audio;
|
||||
|
||||
public void Draw(GameTime gameTime)
|
||||
{
|
||||
@@ -23,6 +25,7 @@ internal abstract class GameLoopBase(AlienAttackGame game) : IGameLoop
|
||||
|
||||
public void Update(GameTime gameTime)
|
||||
{
|
||||
Audio.UpdateWithDuck(gameTime);
|
||||
OnUpdate(gameTime);
|
||||
}
|
||||
|
||||
|
||||
@@ -47,5 +47,7 @@ internal class Bullet(float x, float y, float xVel, float yVel, Sprite owner) :
|
||||
}
|
||||
|
||||
context.SpawnSprite(new MiniExplosion((int)XPosition, (int)YPosition, xVel, yVel));
|
||||
|
||||
context.AudioManager.PlayImpact();
|
||||
}
|
||||
}
|
||||
@@ -88,6 +88,8 @@ internal class GreenEnemy : EnemyShip
|
||||
context.SpawnSprite(new MinigunBulletSmall(originX + 14, YPosition + BoundBox.Height - 12, 0, 2 + YVelocity, this));
|
||||
|
||||
CurrentFireThreshold = FireThreshold;
|
||||
|
||||
context.AudioManager.PlayEnemyFire();
|
||||
}
|
||||
|
||||
//CheckMove(context);
|
||||
@@ -100,10 +102,12 @@ internal class GreenEnemy : EnemyShip
|
||||
{
|
||||
context.SpawnSprite(new Explosion((int)XPosition, (int)YPosition, XVelocity, YVelocity));
|
||||
|
||||
int number = context.Random.Next(1, 7);
|
||||
//int number = context.Random.Next(1, 7);
|
||||
|
||||
SoundEffect soundEffect = context.Content.Load<SoundEffect>(@$"Sfx\Explosions\EXPLDsgn_Explosion Impact_0{number}_SFRMS_SCIWPNS");
|
||||
soundEffect.Play(0.95f, (float)(context.Random.NextDouble() * 0.1 - 0.05), 0);
|
||||
//SoundEffect soundEffect = context.Content.Load<SoundEffect>(@$"Sfx\Explosions\EXPLDsgn_Explosion Impact_0{number}_SFRMS_SCIWPNS");
|
||||
//soundEffect.Play(0.95f, (float)(context.Random.NextDouble() * 0.1 - 0.05), 0);
|
||||
|
||||
context.AudioManager.PlayExplosion();
|
||||
}
|
||||
|
||||
private void CheckFire(SpriteUpdateContext context)
|
||||
|
||||
@@ -73,10 +73,12 @@ internal class RedEnemy : EnemyShip
|
||||
{
|
||||
context.SpawnSprite(new Explosion((int)XPosition, (int)YPosition, XVelocity, YVelocity));
|
||||
|
||||
int number = context.Random.Next(1, 7);
|
||||
//int number = context.Random.Next(1, 7);
|
||||
|
||||
SoundEffect soundEffect = context.Content.Load<SoundEffect>(@$"Sfx\Explosions\EXPLDsgn_Explosion Impact_0{number}_SFRMS_SCIWPNS");
|
||||
soundEffect.Play(0.95f, (float)(context.Random.NextDouble() * 0.1 - 0.05), 0);
|
||||
//SoundEffect soundEffect = context.Content.Load<SoundEffect>(@$"Sfx\Explosions\EXPLDsgn_Explosion Impact_0{number}_SFRMS_SCIWPNS");
|
||||
//soundEffect.Play(0.95f, (float)(context.Random.NextDouble() * 0.1 - 0.05), 0);
|
||||
|
||||
context.AudioManager.PlayExplosion();
|
||||
}
|
||||
|
||||
private void TryFire(SpriteUpdateContext context)
|
||||
@@ -94,6 +96,8 @@ internal class RedEnemy : EnemyShip
|
||||
context.SpawnSprite(new MinigunBulletSmall(originX + 14, YPosition + BoundBox.Height - 12, 0, 2 + YVelocity, this));
|
||||
|
||||
CurrentFireThreshold = FireThreshold;
|
||||
|
||||
context.AudioManager.PlayEnemyFire();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -66,10 +66,12 @@ internal class TealEnemy : EnemyShip
|
||||
{
|
||||
context.SpawnSprite(new Explosion((int)XPosition, (int)YPosition, XVelocity, YVelocity));
|
||||
|
||||
int number = context.Random.Next(1, 7);
|
||||
//int number = context.Random.Next(1, 7);
|
||||
|
||||
SoundEffect soundEffect = context.Content.Load<SoundEffect>(@$"Sfx\Explosions\EXPLDsgn_Explosion Impact_0{number}_SFRMS_SCIWPNS");
|
||||
soundEffect.Play(0.95f, (float)(context.Random.NextDouble() * 0.1 - 0.05), 0);
|
||||
//SoundEffect soundEffect = context.Content.Load<SoundEffect>(@$"Sfx\Explosions\EXPLDsgn_Explosion Impact_0{number}_SFRMS_SCIWPNS");
|
||||
//soundEffect.Play(0.95f, (float)(context.Random.NextDouble() * 0.1 - 0.05), 0);
|
||||
|
||||
context.AudioManager.PlayExplosion();
|
||||
}
|
||||
|
||||
private void TryFire(SpriteUpdateContext context)
|
||||
@@ -87,6 +89,8 @@ internal class TealEnemy : EnemyShip
|
||||
context.SpawnSprite(new MinigunBulletSmall(originX + 14, YPosition + BoundBox.Height - 12, 0, 2 + YVelocity, this));
|
||||
|
||||
CurrentFireThreshold = FireThreshold;
|
||||
|
||||
context.AudioManager.PlayEnemyFire();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -97,11 +97,13 @@ internal class Player : MoveableSprite
|
||||
|
||||
public override void Update(SpriteUpdateContext context)
|
||||
{
|
||||
base.Update(context);
|
||||
|
||||
//UpdateExhaustAnimationThreshold();
|
||||
CheckMove(context);
|
||||
CheckFire(context);
|
||||
|
||||
base.Update(context);
|
||||
//base.Update(context);
|
||||
}
|
||||
|
||||
private void UpdateExhaustAnimationThreshold()
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using AlienAttack.MonoGame.View;
|
||||
using AlienAttack.MonoGame.Audio;
|
||||
using AlienAttack.MonoGame.View;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Content;
|
||||
using System;
|
||||
@@ -12,6 +13,7 @@ public class SpriteUpdateContext(AlienAttackGame game)
|
||||
public required Random Random { get; init; }
|
||||
public required GameTime GameTime { get; init; }
|
||||
public required ContentManager Content { get; init; }
|
||||
public AudioManager AudioManager => game.Audio;
|
||||
}
|
||||
|
||||
public class SpriteCollisionContext(AlienAttackGame game)
|
||||
@@ -21,4 +23,5 @@ public class SpriteCollisionContext(AlienAttackGame game)
|
||||
public required Action<Sprite> SpawnSprite { get; init; }
|
||||
public required Random Random { get; init; }
|
||||
public required ContentManager Content { get; init; }
|
||||
public AudioManager AudioManager => game.Audio;
|
||||
}
|
||||
@@ -22,10 +22,12 @@ public class Minigun : Weapon
|
||||
context.SpawnSprite(bullet1);
|
||||
context.SpawnSprite(bullet2);
|
||||
|
||||
int number = context.Random.Next(1, 7);
|
||||
//int number = context.Random.Next(1, 7);
|
||||
|
||||
SoundEffect soundEffect = context.Content.Load<SoundEffect>(@$"Sfx\GUNAuto_Assault Rifle A Fire_0{number}_SFRMS_SCIWPNS");
|
||||
soundEffect.Play(0.25f, (float)(context.Random.NextDouble() * 0.1 - 0.05), 0);
|
||||
//SoundEffect soundEffect = context.Content.Load<SoundEffect>(@$"Sfx\GUNAuto_Assault Rifle A Fire_0{number}_SFRMS_SCIWPNS");
|
||||
//soundEffect.Play(0.25f, (float)(context.Random.NextDouble() * 0.1 - 0.05), 0);
|
||||
|
||||
context.AudioManager.PlayPlayerFire();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user