diff --git a/AlientAttack.MonoGame/Audio/AudioManager.cs b/AlientAttack.MonoGame/Audio/AudioManager.cs index a98caa9..e87b133 100644 --- a/AlientAttack.MonoGame/Audio/AudioManager.cs +++ b/AlientAttack.MonoGame/Audio/AudioManager.cs @@ -210,6 +210,22 @@ public sealed class AudioManager _playerGunPool2.Add(BulletKind.ProtonMedium, new VariantSoundPool(protonMediumVariants, voicesPerVariant: 1, rng: _random)); _playerGunPool2.Add(BulletKind.ProtonLarge, new VariantSoundPool(protonLargeVariants, voicesPerVariant: 1, rng: _random)); + _enemyGunPool2.Add(BulletKind.MinigunSmall, new VariantSoundPool(minigunSmallVariants, voicesPerVariant: 1, rng: _random)); + //_enemyGunPool2.Add(BulletKind.MinigunMedium, new VariantSoundPool(minigunLargeVariants, voicesPerVariant: 1, rng: _random)); + _enemyGunPool2.Add(BulletKind.MinigunLarge, new VariantSoundPool(minigunLargeVariants, voicesPerVariant: 1, rng: _random)); + + _enemyGunPool2.Add(BulletKind.LaserSmall, new VariantSoundPool(laserSmallVariants, voicesPerVariant: 1, rng: _random)); + _enemyGunPool2.Add(BulletKind.LaserMedium, new VariantSoundPool(laserMediumVariants, voicesPerVariant: 1, rng: _random)); + _enemyGunPool2.Add(BulletKind.LaserLarge, new VariantSoundPool(laserLargeVariants, voicesPerVariant: 1, rng: _random)); + + _enemyGunPool2.Add(BulletKind.PlasmaSmall, new VariantSoundPool(plasmaSmallVariants, voicesPerVariant: 1, rng: _random)); + _enemyGunPool2.Add(BulletKind.PlasmaMedium, new VariantSoundPool(plasmaMediumVariants, voicesPerVariant: 1, rng: _random)); + _enemyGunPool2.Add(BulletKind.PlasmaLarge, new VariantSoundPool(plasmaLargeVariants, voicesPerVariant: 1, rng: _random)); + + _enemyGunPool2.Add(BulletKind.ProtonSmall, new VariantSoundPool(protonSmallVariants, voicesPerVariant: 1, rng: _random)); + _enemyGunPool2.Add(BulletKind.ProtonMedium, new VariantSoundPool(protonMediumVariants, voicesPerVariant: 1, rng: _random)); + _enemyGunPool2.Add(BulletKind.ProtonLarge, new VariantSoundPool(protonLargeVariants, voicesPerVariant: 1, rng: _random)); + } private void LoadEnemyGunPool(ContentManager content) @@ -392,6 +408,25 @@ public sealed class AudioManager ); } + public void PlayEnemyFire(BulletKind bulletKind) + { + if (!_enemyGunLimiter.TryConsume()) + return; + + if (_enemyGunPool2.TryGetValue(bulletKind, out VariantSoundPool soundPool) == false) + return; + + // Bullet sounds should be short + quiet-ish + float baseVol = 0.28f; + float vol = baseVol * RandRange(0.90f, 1.05f); + float pitch = RandRange(-0.07f, 0.07f); + + soundPool.Play( + volume: Clamp01(MasterVolume * SfxVolume * vol), + pitch: pitch + ); + } + public void PlayImpact() { if (!_impactLimiter.TryConsume()) return; diff --git a/AlientAttack.MonoGame/GameLoops/GameLoop.cs b/AlientAttack.MonoGame/GameLoops/GameLoop.cs index 064c952..272f17a 100644 --- a/AlientAttack.MonoGame/GameLoops/GameLoop.cs +++ b/AlientAttack.MonoGame/GameLoops/GameLoop.cs @@ -2,6 +2,7 @@ using AlienAttack.MonoGame.Things.Asteroids; using AlienAttack.MonoGame.Things.Enemies; using AlienAttack.MonoGame.Things.Enemies.Mines; +using AlienAttack.MonoGame.Things.Enemies.Ships.TypeA; using AlienAttack.MonoGame.Things.Enemies.Turrets; using AlienAttack.MonoGame.Things.Stars; using AlienAttack.MonoGame.View; @@ -330,24 +331,24 @@ internal class GameLoop : GameLoopBase { int randomNumber = _random.Next(0, 100); - //if (randomNumber == 0) - //{ - // GreenEnemy enemy = new(_random.Next(0, ViewTransform.ScreenWidth - 64), -64); - // Sprites.Add(enemy); - // _spawnNewEnemyThreshold = 100 + _random.Next(0, 100); - //} - //else if (randomNumber == 1) - //{ - // RedEnemy enemy = new(_random.Next(0, ViewTransform.ScreenWidth - 64), -64); - // Sprites.Add(enemy); - // _spawnNewEnemyThreshold = 100 + _random.Next(0, 100); - //} - //else if (randomNumber == 2) - //{ - // TealEnemy enemy = new(_random.Next(0, ViewTransform.ScreenWidth - 64), -64); - // Sprites.Add(enemy); - // _spawnNewEnemyThreshold = 100 + _random.Next(0, 100); - //} + if (randomNumber == 0) + { + GreenShipTypeA ship = new(_random.Next(0, ViewTransform.ScreenWidth - 64), -64); + Sprites.Add(ship); + _spawnNewEnemyThreshold = 100 + _random.Next(0, 100); + } + else if (randomNumber == 1) + { + RedShipTypeA enemy = new(_random.Next(0, ViewTransform.ScreenWidth - 64), -64); + Sprites.Add(enemy); + _spawnNewEnemyThreshold = 100 + _random.Next(0, 100); + } + else if (randomNumber == 2) + { + TealShipTypeA enemy = new(_random.Next(0, ViewTransform.ScreenWidth - 64), -64); + Sprites.Add(enemy); + _spawnNewEnemyThreshold = 100 + _random.Next(0, 100); + } //else if (randomNumber == 3) //{ // Enemy02Green enemy = new(_random.Next(0, ViewTransform.ScreenWidth - 64), -64); @@ -366,7 +367,7 @@ internal class GameLoop : GameLoopBase // Sprites.Add(enemy); // _spawnNewEnemyThreshold = 100 + _random.Next(0, 100); //} - if (randomNumber == 6) + else if (randomNumber == 6) { GreenMine enemy = new(_random.Next(0, ViewTransform.ScreenWidth - Mine.Width), -Mine.Height); Sprites.Add(enemy); diff --git a/AlientAttack.MonoGame/Things/Enemies/Mines/Mine.cs b/AlientAttack.MonoGame/Things/Enemies/Mines/Mine.cs index 4b1dfe9..1da42e1 100644 --- a/AlientAttack.MonoGame/Things/Enemies/Mines/Mine.cs +++ b/AlientAttack.MonoGame/Things/Enemies/Mines/Mine.cs @@ -19,6 +19,10 @@ public abstract class Mine : MoveableSprite protected float RotationSpeed { get; set; } = 1.5f; protected double DistanceToPlayer { get; set; } = double.MaxValue; + private MineState State { get; set; } = MineState.Drifting; + private Vector2? CurrentTarget { get; set; } + + public Mine(int x, int y) : base(x, y) { Origin = new(30, 33); @@ -77,6 +81,19 @@ public abstract class Mine : MoveableSprite } Rotation = MathHelper.WrapAngle(Rotation + RotationSpeed * context.DeltaTime); + + switch (State) + { + case MineState: + default: + break; + } + } + + protected void Charge(Vector2 target) + { + State = MineState.Charging; + CurrentTarget = target; } private void UpdateDistanceToPlayer(SpriteUpdateContext context) diff --git a/AlientAttack.MonoGame/Things/Enemies/Mines/MineState.cs b/AlientAttack.MonoGame/Things/Enemies/Mines/MineState.cs new file mode 100644 index 0000000..2c12d14 --- /dev/null +++ b/AlientAttack.MonoGame/Things/Enemies/Mines/MineState.cs @@ -0,0 +1,7 @@ +namespace AlienAttack.MonoGame.Things.Enemies.Mines; + +public enum MineState +{ + Drifting, + Charging +} \ No newline at end of file diff --git a/AlientAttack.MonoGame/Things/Enemies/Ships/TypeA/GreenShipTypeA.cs b/AlientAttack.MonoGame/Things/Enemies/Ships/TypeA/GreenShipTypeA.cs index 9755c79..23d0982 100644 --- a/AlientAttack.MonoGame/Things/Enemies/Ships/TypeA/GreenShipTypeA.cs +++ b/AlientAttack.MonoGame/Things/Enemies/Ships/TypeA/GreenShipTypeA.cs @@ -20,7 +20,25 @@ public class GreenShipTypeA : ShipTypeA { BoundBox = new Rectangle(0, 0, 64, 64); YVelocity = 1; - ActiveWeapons.Add(new Minigun()); + + WeaponDef weaponDef = new() + { + Name = "Weapon 1", + Bullet = BulletDefinitions.MinigunSmall, + Pattern = ShotPatterns.ReverseDouble, + FireSfxKey = "" + }; + + WeaponState weasponState = new() + { + FireThreshold = 20, + SpeedMultiplier = 1f, + DamageBonus = 0 + }; + + ConfigurableWeapon configurableWeapon = new(weaponDef, weasponState); + + ActiveWeapons.Add(configurableWeapon); //ActiveWeapons.Add(new FastMinigun()); } @@ -36,21 +54,34 @@ public class GreenShipTypeA : ShipTypeA protected override void TryFire(SpriteUpdateContext context) { - if (CurrentFireThreshold > 0) + //if (CurrentFireThreshold > 0) + //{ + // CurrentFireThreshold--; + //} + + //if (CurrentFireThreshold == 0 && context.Random.Next(0, 100) == 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)); + + // CurrentFireThreshold = FireThreshold; + + // context.AudioManager.PlayEnemyFire(); + //} + + foreach (IWeapon weapon in ActiveWeapons) { - CurrentFireThreshold--; + weapon.UpdateFireThreshold(); } - if (CurrentFireThreshold == 0 && context.Random.Next(0, 100) == 1) + if (context.Random.Next(0, 100) != 1) + return; + + foreach (IWeapon weapon in ActiveWeapons) { - 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)); - - CurrentFireThreshold = FireThreshold; - - context.AudioManager.PlayEnemyFire(); + weapon.TryFire(this, context); } } diff --git a/AlientAttack.MonoGame/Things/Enemies/Ships/TypeA/RedShipTypeA.cs b/AlientAttack.MonoGame/Things/Enemies/Ships/TypeA/RedShipTypeA.cs index 58d9947..7c3898c 100644 --- a/AlientAttack.MonoGame/Things/Enemies/Ships/TypeA/RedShipTypeA.cs +++ b/AlientAttack.MonoGame/Things/Enemies/Ships/TypeA/RedShipTypeA.cs @@ -1,6 +1,8 @@ using AlienAttack.MonoGame.Things.Bullets; +using AlienAttack.MonoGame.Things.Weapons; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; +using System.Collections.Generic; namespace AlienAttack.MonoGame.Things.Enemies.Ships.TypeA; @@ -9,11 +11,31 @@ public class RedShipTypeA : ShipTypeA protected int FireThreshold => 20; protected int CurrentFireThreshold { get; set; } = 20; protected override int Health { get; set; } = 5; + protected ICollection ActiveWeapons = []; public RedShipTypeA(int x, int y) : base(x, y) { BoundBox = new Rectangle(0, 0, 64, 64); YVelocity = 1.5f; + + WeaponDef weaponDef = new() + { + Name = "Weapon 1", + Bullet = BulletDefinitions.MinigunSmall, + Pattern = ShotPatterns.ReverseTripleSpread, + FireSfxKey = "" + }; + + WeaponState weasponState = new() + { + FireThreshold = 20, + SpeedMultiplier = 1f, + DamageBonus = 0 + }; + + ConfigurableWeapon configurableWeapon = new(weaponDef, weasponState); + + ActiveWeapons.Add(configurableWeapon); } public override void Draw(SpriteDrawArgs args) @@ -53,22 +75,35 @@ public class RedShipTypeA : ShipTypeA protected override void TryFire(SpriteUpdateContext context) { - if (CurrentFireThreshold > 0) + //if (CurrentFireThreshold > 0) + //{ + // CurrentFireThreshold--; + //} + + //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, -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; + + // context.AudioManager.PlayEnemyFire(); + //} + + foreach (IWeapon weapon in ActiveWeapons) { - CurrentFireThreshold--; + weapon.UpdateFireThreshold(); } - if (CurrentFireThreshold == 0 && context.Random.Next(0, 50) == 1) + if (context.Random.Next(0, 50) != 1) + return; + + foreach (IWeapon weapon in ActiveWeapons) { - float originX = XPosition + (BoundBox.Width / 2) - (7 / 2); - - 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; - - context.AudioManager.PlayEnemyFire(); + weapon.TryFire(this, context); } } } \ No newline at end of file diff --git a/AlientAttack.MonoGame/Things/Enemies/Ships/TypeA/TealShipTypeA.cs b/AlientAttack.MonoGame/Things/Enemies/Ships/TypeA/TealShipTypeA.cs index bde8fce..e903df1 100644 --- a/AlientAttack.MonoGame/Things/Enemies/Ships/TypeA/TealShipTypeA.cs +++ b/AlientAttack.MonoGame/Things/Enemies/Ships/TypeA/TealShipTypeA.cs @@ -1,6 +1,8 @@ using AlienAttack.MonoGame.Things.Bullets; +using AlienAttack.MonoGame.Things.Weapons; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; +using System.Collections.Generic; namespace AlienAttack.MonoGame.Things.Enemies.Ships.TypeA; @@ -9,12 +11,32 @@ public class TealShipTypeA : ShipTypeA protected int FireThreshold => 20; protected int CurrentFireThreshold { get; set; } = 20; protected override int Health { get; set; } = 5; + protected ICollection ActiveWeapons = []; public TealShipTypeA(int x, int y) : base(x, y) { BoundBox = new Rectangle(0, 0, 64, 64); YVelocity = 1; XVelocity = 3; + + WeaponDef weaponDef = new() + { + Name = "Weapon 1", + Bullet = BulletDefinitions.ProtonLarge, + Pattern = ShotPatterns.ReverseTripleSpread, + FireSfxKey = "" + }; + + WeaponState weasponState = new() + { + FireThreshold = 20, + SpeedMultiplier = 1f, + DamageBonus = 0 + }; + + ConfigurableWeapon configurableWeapon = new(weaponDef, weasponState); + + ActiveWeapons.Add(configurableWeapon); } public override void Draw(SpriteDrawArgs args) @@ -45,25 +67,38 @@ public class TealShipTypeA : ShipTypeA protected override void TryFire(SpriteUpdateContext context) { - if (CurrentFireThreshold > 0) + //if (CurrentFireThreshold > 0) + //{ + // CurrentFireThreshold--; + //} + + //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; + + // context.AudioManager.PlayEnemyFire(); + //} + + foreach (IWeapon weapon in ActiveWeapons) { - CurrentFireThreshold--; + weapon.UpdateFireThreshold(); } - if (CurrentFireThreshold == 0 && context.Random.Next(0, 50) == 1) + if (context.Random.Next(0, 50) != 1) + return; + + foreach (IWeapon weapon in ActiveWeapons) { - 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; - - context.AudioManager.PlayEnemyFire(); + weapon.TryFire(this, context); } } } \ No newline at end of file diff --git a/AlientAttack.MonoGame/Things/Player.cs b/AlientAttack.MonoGame/Things/Player.cs index 27b1ce3..361667d 100644 --- a/AlientAttack.MonoGame/Things/Player.cs +++ b/AlientAttack.MonoGame/Things/Player.cs @@ -36,7 +36,7 @@ public record DrawState public SpriteEffects SpriteEffects { get; init; } } -public class Player : MoveableSprite +public class Player : Ship { protected PlayerHorizontalMoveState MoveState = PlayerHorizontalMoveState.None; protected MoveFlag MoveFlags; @@ -125,7 +125,7 @@ public class Player : MoveableSprite //ActiveWeapons.Add(configurableWeapon2); } - public Vector2 GetMuzzleLocal(MuzzleId muzzle) + public override Vector2 GetMuzzleLocal(MuzzleId muzzle) { switch (muzzle) { @@ -283,24 +283,24 @@ public class Player : MoveableSprite XVelocity *= 1.5f; } - if (XPosition < 0) + if (XPosition - Origin.X < 0) { - XPosition = 0; + XPosition = 0 + Origin.X; } - if (XPosition + BoundBox.Width > context.ViewTransform.ScreenWidth) + if (XPosition + BoundBox.Width - Origin.X > context.ViewTransform.ScreenWidth) { - XPosition = context.ViewTransform.ScreenWidth - BoundBox.Width; + XPosition = context.ViewTransform.ScreenWidth - BoundBox.Width + Origin.X; } - if (YPosition < 0) + if (YPosition - Origin.Y < 0) { - YPosition = 0; + YPosition = 0 + Origin.Y; } - if (YPosition + BoundBox.Height > context.ViewTransform.ScreenHeight) + if (YPosition + BoundBox.Height - Origin.Y > context.ViewTransform.ScreenHeight) { - YPosition = context.ViewTransform.ScreenHeight - BoundBox.Height; + YPosition = context.ViewTransform.ScreenHeight - BoundBox.Height + Origin.Y; } } diff --git a/AlientAttack.MonoGame/Things/Weapons/ConfigurableWeapon.cs b/AlientAttack.MonoGame/Things/Weapons/ConfigurableWeapon.cs index 71f5253..71a8337 100644 --- a/AlientAttack.MonoGame/Things/Weapons/ConfigurableWeapon.cs +++ b/AlientAttack.MonoGame/Things/Weapons/ConfigurableWeapon.cs @@ -1,4 +1,5 @@ -using AlienAttack.MonoGame.Things.Muzzles; +using AlienAttack.MonoGame.Things.Enemies.Ships; +using AlienAttack.MonoGame.Things.Muzzles; namespace AlienAttack.MonoGame.Things.Weapons; @@ -8,13 +9,13 @@ public class ConfigurableWeapon(WeaponDef def, WeaponState state) : Weapon public override void Fire(Sprite owner, SpriteUpdateContext context) { - if (owner is not Player player) return; + if (owner is not Ship ship) return; foreach (var shot in def.Pattern.Shots) { // muzzle local -> world - var muzzleLocal = player.GetMuzzleLocal(shot.Muzzle); // make a fast lookup - var muzzleWorld = MuzzleMath.GetMuzzleWorld(player, muzzleLocal); + var muzzleLocal = ship.GetMuzzleLocal(shot.Muzzle); // make a fast lookup + var muzzleWorld = MuzzleMath.GetMuzzleWorld(ship, muzzleLocal); // speed upgrade float vx = shot.Velocity.X * state.SpeedMultiplier; @@ -32,6 +33,14 @@ public class ConfigurableWeapon(WeaponDef def, WeaponState state) : Weapon } //context.AudioManager.PlayPlayerFire(); // or use _def.FireSfxKey -> audio routing - context.AudioManager.PlayPlayerFire(def.Bullet.Kind); + + if (owner is Player) + { + context.AudioManager.PlayPlayerFire(def.Bullet.Kind); + } + else + { + context.AudioManager.PlayEnemyFire(def.Bullet.Kind); + } } } \ No newline at end of file diff --git a/AlientAttack.MonoGame/Things/Weapons/ShotPatterns.cs b/AlientAttack.MonoGame/Things/Weapons/ShotPatterns.cs index 72bae3a..a3f670b 100644 --- a/AlientAttack.MonoGame/Things/Weapons/ShotPatterns.cs +++ b/AlientAttack.MonoGame/Things/Weapons/ShotPatterns.cs @@ -40,4 +40,40 @@ public static class ShotPatterns new Shot2(MuzzleId.Right, new Vector2(1, -6), new Vector2(4, 0)) ] }; + + public static readonly ShotPattern ReverseSingle = new() + { + Shots = + [ + new Shot2(MuzzleId.Center, new Vector2(0, 6), new Vector2(4, 0)) + ] + }; + + public static readonly ShotPattern ReverseDouble = new() + { + Shots = + [ + new Shot2(MuzzleId.Left, new Vector2(0, 6), new Vector2(4, 0)), + new Shot2(MuzzleId.Right, new Vector2(0, 6), new Vector2(4, 0)) + ] + }; + + public static readonly ShotPattern ReverseDoubleSpread = new() + { + Shots = + [ + new Shot2(MuzzleId.Left, new Vector2(-1, 6), new Vector2(4, 0)), + new Shot2(MuzzleId.Right, new Vector2(1, 6), new Vector2(4, 0)) + ] + }; + + public static readonly ShotPattern ReverseTripleSpread = new() + { + Shots = + [ + new Shot2(MuzzleId.Left, new Vector2(-1, 6), new Vector2(4, 0)), + new Shot2(MuzzleId.Center, new Vector2(0, 6), new Vector2(4, 0)), + new Shot2(MuzzleId.Right, new Vector2(1, 6), new Vector2(4, 0)) + ] + }; } \ No newline at end of file