Added more sound effects. Added initial weapon muzzle fire logic.
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using AlienAttack.MonoGame.Things.Items;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Audio;
|
||||
using Microsoft.Xna.Framework.Content;
|
||||
using Microsoft.Xna.Framework.Media;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace AlienAttack.MonoGame.Audio;
|
||||
|
||||
@@ -19,6 +21,7 @@ public sealed class AudioManager
|
||||
private VariantSoundPool _enemyGunPool = default!;
|
||||
private VariantSoundPool _explosionPool = default!;
|
||||
private VariantSoundPool _impactPool = default!;
|
||||
private Dictionary<PickupKind, VariantSoundPool> _pickupPool = [];
|
||||
|
||||
// Rate limiters (global caps per category/event)
|
||||
private RateLimiter _playerGunLimiter = new(0.06f); // max ~16 plays/sec
|
||||
@@ -39,16 +42,9 @@ public sealed class AudioManager
|
||||
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);
|
||||
LoadShieldPickupPool(content);
|
||||
LoadAmmoPickupPool(content);
|
||||
LoadRocketsPickupPool(content);
|
||||
}
|
||||
|
||||
private void LoadPlayerGunPool(ContentManager content)
|
||||
@@ -111,6 +107,56 @@ public sealed class AudioManager
|
||||
_explosionPool = new VariantSoundPool(variants, voicesPerVariant: 1, rng: _random);
|
||||
}
|
||||
|
||||
private void LoadShieldPickupPool(ContentManager content)
|
||||
{
|
||||
var shieldVariants = new[]
|
||||
{
|
||||
content.Load<SoundEffect>("Sfx/Shield/SCIEnrg_Shield Activate_01_SFRMS_SCIWPNS"),
|
||||
content.Load<SoundEffect>("Sfx/Shield/SCIEnrg_Shield Activate_02_SFRMS_SCIWPNS"),
|
||||
content.Load<SoundEffect>("Sfx/Shield/SCIEnrg_Shield Activate_03_SFRMS_SCIWPNS"),
|
||||
content.Load<SoundEffect>("Sfx/Shield/SCIEnrg_Shield Activate_04_SFRMS_SCIWPNS"),
|
||||
content.Load<SoundEffect>("Sfx/Shield/SCIEnrg_Shield Activate_05_SFRMS_SCIWPNS")
|
||||
};
|
||||
|
||||
_pickupPool.Add(PickupKind.Shield, new VariantSoundPool(shieldVariants, voicesPerVariant: 1, rng: _random));
|
||||
}
|
||||
|
||||
private void LoadAmmoPickupPool(ContentManager content)
|
||||
{
|
||||
var variants = new[]
|
||||
{
|
||||
content.Load<SoundEffect>("Sfx/Reload/GUNMech_Insert Clip_01_SFRMS_SCIWPNS"),
|
||||
content.Load<SoundEffect>("Sfx/Reload/GUNMech_Insert Clip_02_SFRMS_SCIWPNS"),
|
||||
content.Load<SoundEffect>("Sfx/Reload/GUNMech_Insert Clip_03_SFRMS_SCIWPNS"),
|
||||
content.Load<SoundEffect>("Sfx/Reload/GUNMech_Insert Clip_04_SFRMS_SCIWPNS"),
|
||||
content.Load<SoundEffect>("Sfx/Reload/GUNMech_Insert Clip_05_SFRMS_SCIWPNS")
|
||||
};
|
||||
|
||||
_pickupPool.Add(PickupKind.Ammo, new VariantSoundPool(variants, voicesPerVariant: 1, rng: _random));
|
||||
}
|
||||
|
||||
private void LoadRocketsPickupPool(ContentManager content)
|
||||
{
|
||||
var variants = new[]
|
||||
{
|
||||
content.Load<SoundEffect>("Sfx/Rocket Launcher/GUNMech_Rocket Launcher Reload_01_SFRMS_SCIWPNS"),
|
||||
content.Load<SoundEffect>("Sfx/Rocket Launcher/GUNMech_Rocket Launcher Reload_02_SFRMS_SCIWPNS"),
|
||||
content.Load<SoundEffect>("Sfx/Rocket Launcher/GUNMech_Rocket Launcher Reload_03_SFRMS_SCIWPNS"),
|
||||
content.Load<SoundEffect>("Sfx/Rocket Launcher/GUNMech_Rocket Launcher Reload_04_SFRMS_SCIWPNS"),
|
||||
content.Load<SoundEffect>("Sfx/Rocket Launcher/GUNMech_Rocket Launcher Reload_05_SFRMS_SCIWPNS"),
|
||||
content.Load<SoundEffect>("Sfx/Rocket Launcher/GUNMech_Rocket Launcher Reload_06_SFRMS_SCIWPNS"),
|
||||
content.Load<SoundEffect>("Sfx/Rocket Launcher/GUNMech_Rocket Launcher Reload_07_SFRMS_SCIWPNS"),
|
||||
content.Load<SoundEffect>("Sfx/Rocket Launcher/GUNMech_Rocket Launcher Reload_08_SFRMS_SCIWPNS"),
|
||||
content.Load<SoundEffect>("Sfx/Rocket Launcher/GUNMech_Rocket Launcher Reload_09_SFRMS_SCIWPNS"),
|
||||
content.Load<SoundEffect>("Sfx/Rocket Launcher/GUNMech_Rocket Launcher Reload_10_SFRMS_SCIWPNS"),
|
||||
content.Load<SoundEffect>("Sfx/Rocket Launcher/GUNMech_Rocket Launcher Reload_11_SFRMS_SCIWPNS"),
|
||||
};
|
||||
|
||||
_pickupPool.Add(PickupKind.Rockets, new VariantSoundPool(variants, voicesPerVariant: 1, rng: _random));
|
||||
}
|
||||
|
||||
//GUNMech_Rocket Launcher Reload_01_SFRMS_SCIWPNS
|
||||
|
||||
// Call this once per frame
|
||||
public void Update(GameTime gameTime)
|
||||
{
|
||||
@@ -192,6 +238,21 @@ public sealed class AudioManager
|
||||
}
|
||||
}
|
||||
|
||||
public void PlayPickup(PickupKind kind)
|
||||
{
|
||||
if (_pickupPool.TryGetValue(kind, out VariantSoundPool pool) == false)
|
||||
return;
|
||||
|
||||
float baseVol = 0.85f;
|
||||
float vol = baseVol * RandRange(0.95f, 1.05f);
|
||||
float pitch = RandRange(-0.04f, 0.04f);
|
||||
|
||||
pool.Play(
|
||||
volume: Clamp01(MasterVolume * SfxVolume * vol),
|
||||
pitch: pitch
|
||||
);
|
||||
}
|
||||
|
||||
// -----------------------
|
||||
// Music
|
||||
// -----------------------
|
||||
|
||||
@@ -223,6 +223,138 @@
|
||||
/processorParam:Quality=Best
|
||||
/build:Sfx/Pistol/GUNPis_Pistol Fire_06_SFRMS_SCIWPNS.wav;Sfx/Pistol/GUNPis_Pistol Fire_06_SFRMS_SCIWPNS
|
||||
|
||||
#begin Sfx/Reload/GUNMech_Insert Clip_01_SFRMS_SCIWPNS.wav
|
||||
/importer:WavImporter
|
||||
/processor:SoundEffectProcessor
|
||||
/processorParam:Quality=Best
|
||||
/build:Sfx/Reload/GUNMech_Insert Clip_01_SFRMS_SCIWPNS.wav;Sfx/Reload/GUNMech_Insert Clip_01_SFRMS_SCIWPNS
|
||||
|
||||
#begin Sfx/Reload/GUNMech_Insert Clip_02_SFRMS_SCIWPNS.wav
|
||||
/importer:WavImporter
|
||||
/processor:SoundEffectProcessor
|
||||
/processorParam:Quality=Best
|
||||
/build:Sfx/Reload/GUNMech_Insert Clip_02_SFRMS_SCIWPNS.wav;Sfx/Reload/GUNMech_Insert Clip_02_SFRMS_SCIWPNS
|
||||
|
||||
#begin Sfx/Reload/GUNMech_Insert Clip_03_SFRMS_SCIWPNS.wav
|
||||
/importer:WavImporter
|
||||
/processor:SoundEffectProcessor
|
||||
/processorParam:Quality=Best
|
||||
/build:Sfx/Reload/GUNMech_Insert Clip_03_SFRMS_SCIWPNS.wav;Sfx/Reload/GUNMech_Insert Clip_03_SFRMS_SCIWPNS
|
||||
|
||||
#begin Sfx/Reload/GUNMech_Insert Clip_04_SFRMS_SCIWPNS.wav
|
||||
/importer:WavImporter
|
||||
/processor:SoundEffectProcessor
|
||||
/processorParam:Quality=Best
|
||||
/build:Sfx/Reload/GUNMech_Insert Clip_04_SFRMS_SCIWPNS.wav;Sfx/Reload/GUNMech_Insert Clip_04_SFRMS_SCIWPNS
|
||||
|
||||
#begin Sfx/Reload/GUNMech_Insert Clip_05_SFRMS_SCIWPNS.wav
|
||||
/importer:WavImporter
|
||||
/processor:SoundEffectProcessor
|
||||
/processorParam:Quality=Best
|
||||
/build:Sfx/Reload/GUNMech_Insert Clip_05_SFRMS_SCIWPNS.wav;Sfx/Reload/GUNMech_Insert Clip_05_SFRMS_SCIWPNS
|
||||
|
||||
#begin Sfx/Rocket Launcher/GUNArtl_Rocket Launcher Fire_01_SFRMS_SCIWPNS.wav
|
||||
/importer:WavImporter
|
||||
/processor:SoundEffectProcessor
|
||||
/processorParam:Quality=Best
|
||||
/build:Sfx/Rocket Launcher/GUNArtl_Rocket Launcher Fire_01_SFRMS_SCIWPNS.wav;Sfx/Rocket Launcher/GUNArtl_Rocket Launcher Fire_01_SFRMS_SCIWPNS
|
||||
|
||||
#begin Sfx/Rocket Launcher/GUNArtl_Rocket Launcher Fire_02_SFRMS_SCIWPNS.wav
|
||||
/importer:WavImporter
|
||||
/processor:SoundEffectProcessor
|
||||
/processorParam:Quality=Best
|
||||
/build:Sfx/Rocket Launcher/GUNArtl_Rocket Launcher Fire_02_SFRMS_SCIWPNS.wav;Sfx/Rocket Launcher/GUNArtl_Rocket Launcher Fire_02_SFRMS_SCIWPNS
|
||||
|
||||
#begin Sfx/Rocket Launcher/GUNArtl_Rocket Launcher Fire_03_SFRMS_SCIWPNS.wav
|
||||
/importer:WavImporter
|
||||
/processor:SoundEffectProcessor
|
||||
/processorParam:Quality=Best
|
||||
/build:Sfx/Rocket Launcher/GUNArtl_Rocket Launcher Fire_03_SFRMS_SCIWPNS.wav;Sfx/Rocket Launcher/GUNArtl_Rocket Launcher Fire_03_SFRMS_SCIWPNS
|
||||
|
||||
#begin Sfx/Rocket Launcher/GUNArtl_Rocket Launcher Fire_04_SFRMS_SCIWPNS.wav
|
||||
/importer:WavImporter
|
||||
/processor:SoundEffectProcessor
|
||||
/processorParam:Quality=Best
|
||||
/build:Sfx/Rocket Launcher/GUNArtl_Rocket Launcher Fire_04_SFRMS_SCIWPNS.wav;Sfx/Rocket Launcher/GUNArtl_Rocket Launcher Fire_04_SFRMS_SCIWPNS
|
||||
|
||||
#begin Sfx/Rocket Launcher/GUNArtl_Rocket Launcher Fire_05_SFRMS_SCIWPNS.wav
|
||||
/importer:WavImporter
|
||||
/processor:SoundEffectProcessor
|
||||
/processorParam:Quality=Best
|
||||
/build:Sfx/Rocket Launcher/GUNArtl_Rocket Launcher Fire_05_SFRMS_SCIWPNS.wav;Sfx/Rocket Launcher/GUNArtl_Rocket Launcher Fire_05_SFRMS_SCIWPNS
|
||||
|
||||
#begin Sfx/Rocket Launcher/GUNArtl_Rocket Launcher Fire_06_SFRMS_SCIWPNS.wav
|
||||
/importer:WavImporter
|
||||
/processor:SoundEffectProcessor
|
||||
/processorParam:Quality=Best
|
||||
/build:Sfx/Rocket Launcher/GUNArtl_Rocket Launcher Fire_06_SFRMS_SCIWPNS.wav;Sfx/Rocket Launcher/GUNArtl_Rocket Launcher Fire_06_SFRMS_SCIWPNS
|
||||
|
||||
#begin Sfx/Rocket Launcher/GUNMech_Rocket Launcher Reload_01_SFRMS_SCIWPNS.wav
|
||||
/importer:WavImporter
|
||||
/processor:SoundEffectProcessor
|
||||
/processorParam:Quality=Best
|
||||
/build:Sfx/Rocket Launcher/GUNMech_Rocket Launcher Reload_01_SFRMS_SCIWPNS.wav;Sfx/Rocket Launcher/GUNMech_Rocket Launcher Reload_01_SFRMS_SCIWPNS
|
||||
|
||||
#begin Sfx/Rocket Launcher/GUNMech_Rocket Launcher Reload_02_SFRMS_SCIWPNS.wav
|
||||
/importer:WavImporter
|
||||
/processor:SoundEffectProcessor
|
||||
/processorParam:Quality=Best
|
||||
/build:Sfx/Rocket Launcher/GUNMech_Rocket Launcher Reload_02_SFRMS_SCIWPNS.wav;Sfx/Rocket Launcher/GUNMech_Rocket Launcher Reload_02_SFRMS_SCIWPNS
|
||||
|
||||
#begin Sfx/Rocket Launcher/GUNMech_Rocket Launcher Reload_03_SFRMS_SCIWPNS.wav
|
||||
/importer:WavImporter
|
||||
/processor:SoundEffectProcessor
|
||||
/processorParam:Quality=Best
|
||||
/build:Sfx/Rocket Launcher/GUNMech_Rocket Launcher Reload_03_SFRMS_SCIWPNS.wav;Sfx/Rocket Launcher/GUNMech_Rocket Launcher Reload_03_SFRMS_SCIWPNS
|
||||
|
||||
#begin Sfx/Rocket Launcher/GUNMech_Rocket Launcher Reload_04_SFRMS_SCIWPNS.wav
|
||||
/importer:WavImporter
|
||||
/processor:SoundEffectProcessor
|
||||
/processorParam:Quality=Best
|
||||
/build:Sfx/Rocket Launcher/GUNMech_Rocket Launcher Reload_04_SFRMS_SCIWPNS.wav;Sfx/Rocket Launcher/GUNMech_Rocket Launcher Reload_04_SFRMS_SCIWPNS
|
||||
|
||||
#begin Sfx/Rocket Launcher/GUNMech_Rocket Launcher Reload_05_SFRMS_SCIWPNS.wav
|
||||
/importer:WavImporter
|
||||
/processor:SoundEffectProcessor
|
||||
/processorParam:Quality=Best
|
||||
/build:Sfx/Rocket Launcher/GUNMech_Rocket Launcher Reload_05_SFRMS_SCIWPNS.wav;Sfx/Rocket Launcher/GUNMech_Rocket Launcher Reload_05_SFRMS_SCIWPNS
|
||||
|
||||
#begin Sfx/Rocket Launcher/GUNMech_Rocket Launcher Reload_06_SFRMS_SCIWPNS.wav
|
||||
/importer:WavImporter
|
||||
/processor:SoundEffectProcessor
|
||||
/processorParam:Quality=Best
|
||||
/build:Sfx/Rocket Launcher/GUNMech_Rocket Launcher Reload_06_SFRMS_SCIWPNS.wav;Sfx/Rocket Launcher/GUNMech_Rocket Launcher Reload_06_SFRMS_SCIWPNS
|
||||
|
||||
#begin Sfx/Rocket Launcher/GUNMech_Rocket Launcher Reload_07_SFRMS_SCIWPNS.wav
|
||||
/importer:WavImporter
|
||||
/processor:SoundEffectProcessor
|
||||
/processorParam:Quality=Best
|
||||
/build:Sfx/Rocket Launcher/GUNMech_Rocket Launcher Reload_07_SFRMS_SCIWPNS.wav;Sfx/Rocket Launcher/GUNMech_Rocket Launcher Reload_07_SFRMS_SCIWPNS
|
||||
|
||||
#begin Sfx/Rocket Launcher/GUNMech_Rocket Launcher Reload_08_SFRMS_SCIWPNS.wav
|
||||
/importer:WavImporter
|
||||
/processor:SoundEffectProcessor
|
||||
/processorParam:Quality=Best
|
||||
/build:Sfx/Rocket Launcher/GUNMech_Rocket Launcher Reload_08_SFRMS_SCIWPNS.wav;Sfx/Rocket Launcher/GUNMech_Rocket Launcher Reload_08_SFRMS_SCIWPNS
|
||||
|
||||
#begin Sfx/Rocket Launcher/GUNMech_Rocket Launcher Reload_09_SFRMS_SCIWPNS.wav
|
||||
/importer:WavImporter
|
||||
/processor:SoundEffectProcessor
|
||||
/processorParam:Quality=Best
|
||||
/build:Sfx/Rocket Launcher/GUNMech_Rocket Launcher Reload_09_SFRMS_SCIWPNS.wav;Sfx/Rocket Launcher/GUNMech_Rocket Launcher Reload_09_SFRMS_SCIWPNS
|
||||
|
||||
#begin Sfx/Rocket Launcher/GUNMech_Rocket Launcher Reload_10_SFRMS_SCIWPNS.wav
|
||||
/importer:WavImporter
|
||||
/processor:SoundEffectProcessor
|
||||
/processorParam:Quality=Best
|
||||
/build:Sfx/Rocket Launcher/GUNMech_Rocket Launcher Reload_10_SFRMS_SCIWPNS.wav;Sfx/Rocket Launcher/GUNMech_Rocket Launcher Reload_10_SFRMS_SCIWPNS
|
||||
|
||||
#begin Sfx/Rocket Launcher/GUNMech_Rocket Launcher Reload_11_SFRMS_SCIWPNS.wav
|
||||
/importer:WavImporter
|
||||
/processor:SoundEffectProcessor
|
||||
/processorParam:Quality=Best
|
||||
/build:Sfx/Rocket Launcher/GUNMech_Rocket Launcher Reload_11_SFRMS_SCIWPNS.wav;Sfx/Rocket Launcher/GUNMech_Rocket Launcher Reload_11_SFRMS_SCIWPNS
|
||||
|
||||
#begin Sfx/Shield/SCIEnrg_Shield Activate_01_SFRMS_SCIWPNS.wav
|
||||
/importer:WavImporter
|
||||
/processor:SoundEffectProcessor
|
||||
|
||||
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.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -6,9 +6,12 @@ namespace AlienAttack.MonoGame.Things.Bullets;
|
||||
|
||||
internal class MinigunBulletLarge : Bullet
|
||||
{
|
||||
public const int Width = 9;
|
||||
public const int Height = 27;
|
||||
|
||||
public MinigunBulletLarge(float x, float y, float xVel, float yVel, Sprite owner) : base(x, y, xVel, yVel, owner)
|
||||
{
|
||||
BoundBox = new(0, 0, 9, 27);
|
||||
BoundBox = new(0, 0, Width, Height);
|
||||
Damage = 3;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,9 +6,12 @@ namespace AlienAttack.MonoGame.Things.Bullets;
|
||||
|
||||
internal class MinigunBulletMedium : Bullet
|
||||
{
|
||||
public const int Width = 11;
|
||||
public const int Height = 21;
|
||||
|
||||
public MinigunBulletMedium(float x, float y, float xVel, float yVel, Sprite owner) : base(x, y, xVel, yVel, owner)
|
||||
{
|
||||
BoundBox = new(0, 0, 11, 21);
|
||||
BoundBox = new(0, 0, Width, Height);
|
||||
Damage = 2;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,9 +6,12 @@ namespace AlienAttack.MonoGame.Things.Bullets;
|
||||
|
||||
internal class MinigunBulletSmall : Bullet
|
||||
{
|
||||
public const int Width = 11;
|
||||
public const int Height = 21;
|
||||
|
||||
public MinigunBulletSmall(float x, float y, float xVel, float yVel, Sprite owner) : base(x, y, xVel, yVel, owner)
|
||||
{
|
||||
BoundBox = new(0, 0, 7, 17);
|
||||
BoundBox = new(0, 0, Width, Height);
|
||||
Damage = 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ internal class RedEnemy : EnemyShip
|
||||
public RedEnemy(int x, int y) : base(x, y)
|
||||
{
|
||||
BoundBox = new Rectangle(0, 0, 64, 64);
|
||||
YVelocity = 2;
|
||||
YVelocity = 1.5f;
|
||||
}
|
||||
|
||||
public override void Draw(SpriteDrawArgs args)
|
||||
@@ -88,12 +88,13 @@ internal class RedEnemy : EnemyShip
|
||||
CurrentFireThreshold--;
|
||||
}
|
||||
|
||||
if (CurrentFireThreshold == 0 && context.Random.Next(0, 20) == 1)
|
||||
if (CurrentFireThreshold == 0 && context.Random.Next(0, 50) == 1)
|
||||
{
|
||||
float originX = XPosition + (BoundBox.Width / 2) - (7 / 2);
|
||||
|
||||
context.SpawnSprite(new MinigunBulletSmall(originX - 9, YPosition + BoundBox.Height - 12, 0, 2 + YVelocity, this));
|
||||
context.SpawnSprite(new MinigunBulletSmall(originX + 14, YPosition + BoundBox.Height - 12, 0, 2 + YVelocity, this));
|
||||
context.SpawnSprite(new MinigunBulletSmall(originX - 9, YPosition + BoundBox.Height - 12, -1, 2 + YVelocity, this));
|
||||
context.SpawnSprite(new MinigunBulletSmall(originX + 3, YPosition + BoundBox.Height - 12, 0, 2 + YVelocity, this));
|
||||
context.SpawnSprite(new MinigunBulletSmall(originX + 14, YPosition + BoundBox.Height - 12, 1, 2 + YVelocity, this));
|
||||
|
||||
CurrentFireThreshold = FireThreshold;
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
internal class Ammo : Item
|
||||
{
|
||||
protected override PickupKind Kind => PickupKind.Ammo;
|
||||
|
||||
public Ammo(int x, int y) : base(x, y)
|
||||
{
|
||||
TextureName = @$"Sprites\Powerup_Ammo";
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
internal class Energy : Item
|
||||
{
|
||||
protected override PickupKind Kind => PickupKind.Plasma;
|
||||
|
||||
public Energy(int x, int y) : base(x, y)
|
||||
{
|
||||
TextureName = @$"Sprites\Powerup_Energy";
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
internal class Health : Item
|
||||
{
|
||||
protected override PickupKind Kind => PickupKind.Health;
|
||||
|
||||
public Health(int x, int y) : base(x, y)
|
||||
{
|
||||
TextureName = @$"Sprites\Powerup_Health";
|
||||
|
||||
@@ -14,6 +14,8 @@ internal abstract class Item : MoveableSprite
|
||||
|
||||
protected string TextureName;
|
||||
|
||||
protected abstract PickupKind Kind { get; }
|
||||
|
||||
public Item(int x, int y) : base(x, y)
|
||||
{
|
||||
YVelocity = .5f;
|
||||
@@ -61,6 +63,7 @@ internal abstract class Item : MoveableSprite
|
||||
{
|
||||
IsDead = true;
|
||||
ApplyEffect(player);
|
||||
context.AudioManager.PlayPickup(Kind);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
10
AlientAttack.MonoGame/Things/Items/PickupKind.cs
Normal file
10
AlientAttack.MonoGame/Things/Items/PickupKind.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace AlienAttack.MonoGame.Things.Items;
|
||||
|
||||
public enum PickupKind
|
||||
{
|
||||
Health,
|
||||
Shield,
|
||||
Ammo,
|
||||
Rockets,
|
||||
Plasma
|
||||
}
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
internal class Rockets : Item
|
||||
{
|
||||
protected override PickupKind Kind => PickupKind.Rockets;
|
||||
|
||||
public Rockets(int x, int y) : base(x, y)
|
||||
{
|
||||
TextureName = @$"Sprites\Powerup_Rockets";
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
internal class Shields : Item
|
||||
{
|
||||
protected override PickupKind Kind => PickupKind.Shield;
|
||||
|
||||
public Shields(int x, int y) : base(x, y)
|
||||
{
|
||||
TextureName = @$"Sprites\Powerup_Shields";
|
||||
|
||||
9
AlientAttack.MonoGame/Things/Muzzles/Muzzle.cs
Normal file
9
AlientAttack.MonoGame/Things/Muzzles/Muzzle.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace AlienAttack.MonoGame.Things.Muzzles;
|
||||
|
||||
public readonly struct Muzzle(MuzzleId id, Vector2 localPx)
|
||||
{
|
||||
public MuzzleId Id { get; } = id;
|
||||
public Vector2 LocalPx { get; } = localPx;
|
||||
}
|
||||
8
AlientAttack.MonoGame/Things/Muzzles/MuzzleId.cs
Normal file
8
AlientAttack.MonoGame/Things/Muzzles/MuzzleId.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace AlienAttack.MonoGame.Things.Muzzles;
|
||||
|
||||
public enum MuzzleId
|
||||
{
|
||||
Center,
|
||||
Left,
|
||||
Right
|
||||
}
|
||||
20
AlientAttack.MonoGame/Things/Muzzles/MuzzleMath.cs
Normal file
20
AlientAttack.MonoGame/Things/Muzzles/MuzzleMath.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace AlienAttack.MonoGame.Things.Muzzles;
|
||||
|
||||
public static class MuzzleMath
|
||||
{
|
||||
public static Vector2 GetMuzzleWorld(Sprite owner, Vector2 muzzleLocalPx, float ownerScale = 1f)
|
||||
{
|
||||
// Assumes owner.Position is the top-left of the sprite
|
||||
return owner.Position + muzzleLocalPx * ownerScale;
|
||||
}
|
||||
|
||||
public static Vector2 CenterBulletOn(Vector2 muzzleWorld, int bulletW, int bulletH)
|
||||
{
|
||||
return new Vector2(
|
||||
muzzleWorld.X - bulletW / 2f,
|
||||
muzzleWorld.Y - bulletH / 2f
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,13 @@
|
||||
using AlienAttack.MonoGame.Things.Bullets;
|
||||
using AlienAttack.MonoGame.Things.Enemies;
|
||||
using AlienAttack.MonoGame.Things.Items;
|
||||
using AlienAttack.MonoGame.Things.Muzzles;
|
||||
using AlienAttack.MonoGame.Things.Weapons;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Audio;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using Microsoft.Xna.Framework.Input;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using static System.Net.Mime.MediaTypeNames;
|
||||
|
||||
namespace AlienAttack.MonoGame.Things;
|
||||
|
||||
@@ -52,11 +50,19 @@ internal class Player : MoveableSprite
|
||||
public int Health { get; protected set; }
|
||||
public int Shield { get; protected set; }
|
||||
|
||||
public IReadOnlyList<Muzzle> Muzzles { get; } =
|
||||
[
|
||||
new Muzzle(MuzzleId.Center, new Vector2(31.5f, 1f)),
|
||||
new Muzzle(MuzzleId.Left, new Vector2(15f, 27f)),
|
||||
new Muzzle(MuzzleId.Right, new Vector2(47f, 27f)),
|
||||
];
|
||||
|
||||
public Player(int x, int y) : base(x, y)
|
||||
{
|
||||
BoundBox = new Rectangle(0, 0, 64, 64);
|
||||
ActiveWeapons.Add(new Minigun());
|
||||
//ActiveWeapons.Add(new Minigun());
|
||||
//ActiveWeapons.Add(new FastMinigun());
|
||||
ActiveWeapons.Add(new MinigunSpread());
|
||||
Health = 100;
|
||||
Shield = 100;
|
||||
}
|
||||
@@ -336,10 +342,12 @@ internal class Player : MoveableSprite
|
||||
{
|
||||
//SCIEnrg_Shield Activate_01_SFRMS_SCIWPNS
|
||||
|
||||
int number = context.Random.Next(1, 6);
|
||||
//int number = context.Random.Next(1, 6);
|
||||
|
||||
SoundEffect soundEffect = context.Content.Load<SoundEffect>(@$"Sfx\Shield\SCIEnrg_Shield Activate_0{number}_SFRMS_SCIWPNS");
|
||||
soundEffect.Play(0.85f, (float)(context.Random.NextDouble() * 0.1 - 0.05), 0);
|
||||
//SoundEffect soundEffect = context.Content.Load<SoundEffect>(@$"Sfx\Shield\SCIEnrg_Shield Activate_0{number}_SFRMS_SCIWPNS");
|
||||
//soundEffect.Play(0.85f, (float)(context.Random.NextDouble() * 0.1 - 0.05), 0);
|
||||
|
||||
//context.AudioManager.PlayPickup(PickupKind.Shield);
|
||||
|
||||
GiveShield(20);
|
||||
}
|
||||
|
||||
12
AlientAttack.MonoGame/Things/Weapons/Anchor.cs
Normal file
12
AlientAttack.MonoGame/Things/Weapons/Anchor.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
namespace AlienAttack.MonoGame.Things.Weapons;
|
||||
|
||||
public enum Anchor
|
||||
{
|
||||
TopLeft,
|
||||
TopCenter,
|
||||
TopRight,
|
||||
Center,
|
||||
BottomLeft,
|
||||
BottomCenter,
|
||||
BottomRight
|
||||
}
|
||||
43
AlientAttack.MonoGame/Things/Weapons/FireBulletContext.cs
Normal file
43
AlientAttack.MonoGame/Things/Weapons/FireBulletContext.cs
Normal file
@@ -0,0 +1,43 @@
|
||||
using AlienAttack.MonoGame.Things.Bullets;
|
||||
using AlienAttack.MonoGame.Things.Muzzles;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
|
||||
namespace AlienAttack.MonoGame.Things.Weapons;
|
||||
|
||||
internal record FireBulletContext
|
||||
{
|
||||
public Sprite Owner { get; init; }
|
||||
public SpriteUpdateContext SpriteUpdateContext { get; init; }
|
||||
public int BulletWidth { get; init; }
|
||||
public int BulletHeight { get; init; }
|
||||
public Anchor Anchor { get; init; }
|
||||
public Shot[] Shots { get; init; }
|
||||
public Func<float, float, float, float, Sprite, Bullet> Factory { get; init; }
|
||||
}
|
||||
|
||||
public record Shot
|
||||
{
|
||||
public float OffsetX { get; init; }
|
||||
public float OffsetY { get; init; }
|
||||
public float XVelocity { get; init; }
|
||||
public float YVelocity { get; init; }
|
||||
}
|
||||
|
||||
internal record FireBulletFromMuzzleContext
|
||||
{
|
||||
public Sprite Owner { get; init; }
|
||||
public SpriteUpdateContext SpriteUpdateContext { get; init; }
|
||||
public int BulletWidth { get; init; }
|
||||
public int BulletHeight { get; init; }
|
||||
public MuzzleShot[] Shots { get; init; }
|
||||
public Vector2 ExtraOffset { get; init; } = default;
|
||||
public Func<float, float, float, float, Sprite, Bullet> Factory { get; init; }
|
||||
}
|
||||
|
||||
public record MuzzleShot
|
||||
{
|
||||
public MuzzleId Muzzle { get; init; }
|
||||
public float XVelocity { get; init; }
|
||||
public float YVelocity { get; init; }
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
using AlienAttack.MonoGame.Things.Bullets;
|
||||
using Microsoft.Xna.Framework.Audio;
|
||||
using AlienAttack.MonoGame.Things.Muzzles;
|
||||
|
||||
namespace AlienAttack.MonoGame.Things.Weapons;
|
||||
|
||||
public class Minigun : Weapon
|
||||
internal class Minigun : Weapon
|
||||
{
|
||||
public override int FireThreshold => 15;
|
||||
|
||||
@@ -31,7 +31,49 @@ public class Minigun : Weapon
|
||||
}
|
||||
}
|
||||
|
||||
public class FastMinigun : Weapon
|
||||
internal class MinigunSpread : Weapon
|
||||
{
|
||||
public override int FireThreshold => 20;
|
||||
|
||||
public override void Fire(Sprite owner, SpriteUpdateContext context)
|
||||
{
|
||||
// Calculate bullet spawn positions relative to the player's bounding box
|
||||
int x1 = (int)owner.XPosition + 14;
|
||||
int x2 = (int)owner.XPosition + owner.BoundBox.Width - 16;
|
||||
int x3 = (int)owner.XPosition + owner.BoundBox.Width / 2 - 1;
|
||||
int y = (int)owner.YPosition + 10;
|
||||
|
||||
MinigunBulletLarge bullet1 = new(x1, y, -1, -6, owner);
|
||||
MinigunBulletLarge bullet2 = new(x2, y, 1, -6, owner);
|
||||
MinigunBulletLarge bullet3 = new(x3, y-16, 0, -6, owner);
|
||||
|
||||
//context.SpawnSprite(bullet1);
|
||||
//context.SpawnSprite(bullet2);
|
||||
//context.SpawnSprite(bullet3);
|
||||
|
||||
FireBulletFromMuzzleContext fireBulletContext = new()
|
||||
{
|
||||
Owner = owner,
|
||||
SpriteUpdateContext = context,
|
||||
BulletWidth = MinigunBulletLarge.Width,
|
||||
BulletHeight = MinigunBulletLarge.Height,
|
||||
Factory = (x, y, vx, vy2, o) => new MinigunBulletLarge(x, y, vx, vy2, o),
|
||||
ExtraOffset = new(4f, 0),
|
||||
Shots =
|
||||
[
|
||||
new() { Muzzle = MuzzleId.Left, XVelocity = -1, YVelocity = -6 },
|
||||
new() { Muzzle = MuzzleId.Right, XVelocity = 1, YVelocity = -6 },
|
||||
new() { Muzzle = MuzzleId.Center, XVelocity = 0, YVelocity = -6 }
|
||||
]
|
||||
};
|
||||
|
||||
FireFromMuzzle(fireBulletContext);
|
||||
|
||||
context.AudioManager.PlayPlayerFire();
|
||||
}
|
||||
}
|
||||
|
||||
internal class FastMinigun : Weapon
|
||||
{
|
||||
public override int FireThreshold => 10;
|
||||
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
namespace AlienAttack.MonoGame.Things.Weapons;
|
||||
using AlienAttack.MonoGame.Things.Bullets;
|
||||
using AlienAttack.MonoGame.Things.Muzzles;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
public abstract class Weapon : IWeapon
|
||||
namespace AlienAttack.MonoGame.Things.Weapons;
|
||||
|
||||
internal abstract class Weapon : IWeapon
|
||||
{
|
||||
public abstract int FireThreshold { get; }
|
||||
public int CurrentFireThreshold { get; private set; }
|
||||
@@ -23,4 +29,59 @@ public abstract class Weapon : IWeapon
|
||||
}
|
||||
|
||||
public abstract void Fire(Sprite owner, SpriteUpdateContext context);
|
||||
|
||||
protected static void FireBullet(FireBulletContext context)
|
||||
{
|
||||
var (x, y) = ComputeAnchorPosition(context);
|
||||
|
||||
foreach (Shot shot in context.Shots)
|
||||
{
|
||||
Bullet bullet = context.Factory(x + shot.OffsetX, y + shot.OffsetY, shot.XVelocity, shot.YVelocity, context.Owner);
|
||||
context.SpriteUpdateContext.SpawnSprite(bullet);
|
||||
}
|
||||
}
|
||||
|
||||
private static (float x, float y) ComputeAnchorPosition(FireBulletContext context)
|
||||
{
|
||||
Sprite owner = context.Owner;
|
||||
int bw = context.BulletWidth;
|
||||
int bh = context.BulletHeight;
|
||||
Anchor anchor = context.Anchor;
|
||||
|
||||
float left = owner.XPosition;
|
||||
float top = owner.YPosition;
|
||||
float right = owner.XPosition + owner.BoundBox.Width;
|
||||
float bottom = owner.YPosition + owner.BoundBox.Height;
|
||||
|
||||
return anchor switch
|
||||
{
|
||||
Anchor.TopLeft => (left, top - bh),
|
||||
Anchor.TopCenter => (left + (owner.BoundBox.Width - bw) / 2f, top - bh),
|
||||
Anchor.TopRight => (right - bw, top - bh),
|
||||
|
||||
Anchor.Center => (left + (owner.BoundBox.Width - bw) / 2f, top + (owner.BoundBox.Height - bh) / 2f),
|
||||
|
||||
Anchor.BottomLeft => (left, bottom),
|
||||
Anchor.BottomCenter => (left + (owner.BoundBox.Width - bw) / 2f, bottom),
|
||||
Anchor.BottomRight => (right - bw, bottom),
|
||||
|
||||
_ => (left, top)
|
||||
};
|
||||
}
|
||||
|
||||
protected static void FireFromMuzzle(FireBulletFromMuzzleContext context)
|
||||
{
|
||||
if (context.Owner is not Player player)
|
||||
return;
|
||||
|
||||
foreach (MuzzleShot shot in context.Shots)
|
||||
{
|
||||
var m = player.Muzzles.First(x => x.Id == shot.Muzzle).LocalPx;
|
||||
Vector2 worldMuzzle = MuzzleMath.GetMuzzleWorld(player, m);
|
||||
Vector2 bulletPos = MuzzleMath.CenterBulletOn(worldMuzzle, context.BulletWidth, context.BulletHeight) + context.ExtraOffset;
|
||||
|
||||
Bullet bullet = context.Factory(bulletPos.X, bulletPos.Y, shot.XVelocity, shot.YVelocity, context.Owner);
|
||||
context.SpriteUpdateContext.SpawnSprite(bullet);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user