diff --git a/AlientAttack.MonoGame/GameLoops/GameLoop.cs b/AlientAttack.MonoGame/GameLoops/GameLoop.cs index 62b5842..064c952 100644 --- a/AlientAttack.MonoGame/GameLoops/GameLoop.cs +++ b/AlientAttack.MonoGame/GameLoops/GameLoop.cs @@ -330,43 +330,43 @@ 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); - } - else if (randomNumber == 3) - { - Enemy02Green enemy = new(_random.Next(0, ViewTransform.ScreenWidth - 64), -64); - Sprites.Add(enemy); - _spawnNewEnemyThreshold = 100 + _random.Next(0, 100); - } - else if (randomNumber == 4) - { - Enemy02Red enemy = new(_random.Next(0, ViewTransform.ScreenWidth - 64), -64); - Sprites.Add(enemy); - _spawnNewEnemyThreshold = 100 + _random.Next(0, 100); - } - else if (randomNumber == 5) - { - Enemy02Teal enemy = new(_random.Next(0, ViewTransform.ScreenWidth - 64), -64); - Sprites.Add(enemy); - _spawnNewEnemyThreshold = 100 + _random.Next(0, 100); - } - else if (randomNumber == 6) + //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); + //} + //else if (randomNumber == 3) + //{ + // Enemy02Green enemy = new(_random.Next(0, ViewTransform.ScreenWidth - 64), -64); + // Sprites.Add(enemy); + // _spawnNewEnemyThreshold = 100 + _random.Next(0, 100); + //} + //else if (randomNumber == 4) + //{ + // Enemy02Red enemy = new(_random.Next(0, ViewTransform.ScreenWidth - 64), -64); + // Sprites.Add(enemy); + // _spawnNewEnemyThreshold = 100 + _random.Next(0, 100); + //} + //else if (randomNumber == 5) + //{ + // Enemy02Teal enemy = new(_random.Next(0, ViewTransform.ScreenWidth - 64), -64); + // Sprites.Add(enemy); + // _spawnNewEnemyThreshold = 100 + _random.Next(0, 100); + //} + if (randomNumber == 6) { GreenMine enemy = new(_random.Next(0, ViewTransform.ScreenWidth - Mine.Width), -Mine.Height); Sprites.Add(enemy); @@ -408,30 +408,30 @@ internal class GameLoop : GameLoopBase // Sprites.Add(enemy); // _spawnNewEnemyThreshold = 100 + _random.Next(0, 100); //} - else if (randomNumber == 13) - { - AsteroidVariantA enemy = new(_random.Next(0, ViewTransform.ScreenWidth - AsteroidVariantA.Width), -AsteroidVariantA.Height); - Sprites.Add(enemy); - _spawnNewEnemyThreshold = 100 + _random.Next(0, 100); - } - else if (randomNumber == 14) - { - AsteroidVariantB enemy = new(_random.Next(0, ViewTransform.ScreenWidth - AsteroidVariantB.Width), -AsteroidVariantB.Height); - Sprites.Add(enemy); - _spawnNewEnemyThreshold = 100 + _random.Next(0, 100); - } - else if (randomNumber == 15) - { - AsteroidVariantC enemy = new(_random.Next(0, ViewTransform.ScreenWidth - AsteroidVariantC.Width), -AsteroidVariantC.Height); - Sprites.Add(enemy); - _spawnNewEnemyThreshold = 100 + _random.Next(0, 100); - } - else if (randomNumber == 16) - { - AsteroidVariantD enemy = new(_random.Next(0, ViewTransform.ScreenWidth - AsteroidVariantD.Width), -AsteroidVariantD.Height); - Sprites.Add(enemy); - _spawnNewEnemyThreshold = 100 + _random.Next(0, 100); - } + //else if (randomNumber == 13) + //{ + // AsteroidVariantA enemy = new(_random.Next(0, ViewTransform.ScreenWidth - AsteroidVariantA.Width), -AsteroidVariantA.Height); + // Sprites.Add(enemy); + // _spawnNewEnemyThreshold = 100 + _random.Next(0, 100); + //} + //else if (randomNumber == 14) + //{ + // AsteroidVariantB enemy = new(_random.Next(0, ViewTransform.ScreenWidth - AsteroidVariantB.Width), -AsteroidVariantB.Height); + // Sprites.Add(enemy); + // _spawnNewEnemyThreshold = 100 + _random.Next(0, 100); + //} + //else if (randomNumber == 15) + //{ + // AsteroidVariantC enemy = new(_random.Next(0, ViewTransform.ScreenWidth - AsteroidVariantC.Width), -AsteroidVariantC.Height); + // Sprites.Add(enemy); + // _spawnNewEnemyThreshold = 100 + _random.Next(0, 100); + //} + //else if (randomNumber == 16) + //{ + // AsteroidVariantD enemy = new(_random.Next(0, ViewTransform.ScreenWidth - AsteroidVariantD.Width), -AsteroidVariantD.Height); + // Sprites.Add(enemy); + // _spawnNewEnemyThreshold = 100 + _random.Next(0, 100); + //} } } } diff --git a/AlientAttack.MonoGame/Things/Asteroids/AsteroidVariantB.cs b/AlientAttack.MonoGame/Things/Asteroids/AsteroidVariantB.cs index bec3f40..b76b2bf 100644 --- a/AlientAttack.MonoGame/Things/Asteroids/AsteroidVariantB.cs +++ b/AlientAttack.MonoGame/Things/Asteroids/AsteroidVariantB.cs @@ -16,5 +16,6 @@ public class AsteroidVariantB : Asteroid BoundBox = new(0, 0, Width, Height); YVelocity = 2; XVelocity = 0; + RotationSpeed = 4f; } } \ No newline at end of file diff --git a/AlientAttack.MonoGame/Things/Asteroids/AsteroidVariantD.cs b/AlientAttack.MonoGame/Things/Asteroids/AsteroidVariantD.cs index 025e96c..f59da6e 100644 --- a/AlientAttack.MonoGame/Things/Asteroids/AsteroidVariantD.cs +++ b/AlientAttack.MonoGame/Things/Asteroids/AsteroidVariantD.cs @@ -16,5 +16,6 @@ public class AsteroidVariantD : Asteroid BoundBox = new(0, 0, Width, Height); YVelocity = .5f; XVelocity = 0; + RotationSpeed = .5f; } } \ No newline at end of file diff --git a/AlientAttack.MonoGame/Things/Enemies/Mines/BlueMine.cs b/AlientAttack.MonoGame/Things/Enemies/Mines/BlueMine.cs index 105498a..a03254e 100644 --- a/AlientAttack.MonoGame/Things/Enemies/Mines/BlueMine.cs +++ b/AlientAttack.MonoGame/Things/Enemies/Mines/BlueMine.cs @@ -1,8 +1,98 @@ -namespace AlienAttack.MonoGame.Things.Enemies.Mines; +using Microsoft.Xna.Framework; +using System; + +namespace AlienAttack.MonoGame.Things.Enemies.Mines; public class BlueMine(int x, int y) : Mine(x, y) { protected override string CoverColor => "Blue"; protected override float ExplodeRadius => 100f; protected override int MaxHealth => 10; + + protected int IdleThreshold = 100; + protected int CurrentIdleThreshold = 100; + protected bool IsCharging = false; + protected bool TargetReached = false; + protected Vector2 TargetOrigin; + + private const float DriftSpeed = 1f; + private const float ChargeSpeed = 4f; + + protected override void OnUpdate(SpriteUpdateContext context) + { + // During drift + if (!IsCharging) + { + XVelocity = 0; + YVelocity = DriftSpeed; + + CurrentIdleThreshold--; + + if (CurrentIdleThreshold > 0) + return; + + // Time to pick a target and charge + TargetOrigin = PickTargetBelow(context); + IsCharging = true; + RotationSpeed *= ChargeSpeed; + return; + } + + // During charge + Vector2 mineCenter = new(XPosition + Origin.X, YPosition + Origin.Y); + Vector2 toTarget = TargetOrigin - mineCenter; + + float dist = toTarget.Length(); + + // "Arrive" cleanly: if we can reach it this frame, snap + stop charging + float step = ChargeSpeed; // since you're using per-frame velocities + if (dist <= step || dist <= 0.001f) + { + XPosition = TargetOrigin.X - Origin.X; + YPosition = TargetOrigin.Y - Origin.Y; + + IsCharging = false; + RotationSpeed = 1.5f; + CurrentIdleThreshold = IdleThreshold; + + XVelocity = 0; + YVelocity = DriftSpeed; + return; + } + + Vector2 dir = toTarget / dist; + XVelocity = dir.X * ChargeSpeed; + YVelocity = dir.Y * ChargeSpeed; + } + + private Vector2 PickTargetBelow(SpriteUpdateContext context) + { + // Mine center in world coords + float mineCenterX = XPosition + Origin.X; + float mineCenterY = YPosition + Origin.Y; + + int screenW = context.ViewTransform.ScreenWidth; + int screenH = context.ViewTransform.ScreenHeight; + + // Anywhere horizontally: + float x = context.Random.Next(0, screenW); + + // Somewhere below the mine, but still on-screen. + // Clamp minY so Random doesn't throw if we're near bottom. + int minY = (int)MathF.Min(mineCenterY + 32f, screenH - 1); + int maxY = screenH; + + // If we're already basically at the bottom, just pick the bottom row + float y = (minY < maxY) ? context.Random.Next(minY, maxY) : (screenH - 1); + + return new Vector2(x, y); + } + + private Vector2 GetTargetDirection() + { + Vector2 toTarget = TargetOrigin - new Vector2(XPosition + Origin.X, YPosition + Origin.Y); + float dist = toTarget.Length(); + + return toTarget / dist; + } } \ No newline at end of file diff --git a/AlientAttack.MonoGame/Things/Enemies/EnemyShip.cs b/AlientAttack.MonoGame/Things/Enemies/Ships/EnemyShip.cs similarity index 92% rename from AlientAttack.MonoGame/Things/Enemies/EnemyShip.cs rename to AlientAttack.MonoGame/Things/Enemies/Ships/EnemyShip.cs index 973c382..58aae1a 100644 --- a/AlientAttack.MonoGame/Things/Enemies/EnemyShip.cs +++ b/AlientAttack.MonoGame/Things/Enemies/Ships/EnemyShip.cs @@ -1,13 +1,11 @@ using AlienAttack.MonoGame.Things.Bullets; using AlienAttack.MonoGame.Things.Explosions; -using Microsoft.Xna.Framework; -namespace AlienAttack.MonoGame.Things.Enemies; +namespace AlienAttack.MonoGame.Things.Enemies.Ships; -public abstract class EnemyShip : MoveableSprite +public abstract class EnemyShip : Ship { protected abstract int Health { get; set; } - public virtual int CrashDamage => 10; public EnemyShip(int x, int y) : base(x, y) diff --git a/AlientAttack.MonoGame/Things/Enemies/Ships/Ship.cs b/AlientAttack.MonoGame/Things/Enemies/Ships/Ship.cs new file mode 100644 index 0000000..ae1a878 --- /dev/null +++ b/AlientAttack.MonoGame/Things/Enemies/Ships/Ship.cs @@ -0,0 +1,9 @@ +using AlienAttack.MonoGame.Things.Muzzles; +using Microsoft.Xna.Framework; + +namespace AlienAttack.MonoGame.Things.Enemies.Ships; + +public abstract class Ship(int x, int y) : MoveableSprite(x, y) +{ + public abstract Vector2 GetMuzzleLocal(MuzzleId muzzle); +} \ No newline at end of file diff --git a/AlientAttack.MonoGame/Things/Enemies/GreenEnemy.cs b/AlientAttack.MonoGame/Things/Enemies/Ships/TypeA/GreenShipTypeA.cs similarity index 94% rename from AlientAttack.MonoGame/Things/Enemies/GreenEnemy.cs rename to AlientAttack.MonoGame/Things/Enemies/Ships/TypeA/GreenShipTypeA.cs index 62c608f..9755c79 100644 --- a/AlientAttack.MonoGame/Things/Enemies/GreenEnemy.cs +++ b/AlientAttack.MonoGame/Things/Enemies/Ships/TypeA/GreenShipTypeA.cs @@ -5,9 +5,9 @@ using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using System.Collections.Generic; -namespace AlienAttack.MonoGame.Things.Enemies; +namespace AlienAttack.MonoGame.Things.Enemies.Ships.TypeA; -public class GreenEnemy : EnemyShip +public class GreenShipTypeA : ShipTypeA { //Enemy01_Green_Frame_1_png_processed @@ -16,7 +16,7 @@ public class GreenEnemy : EnemyShip protected int CurrentFireThreshold { get; set; } = 20; protected override int Health { get; set; } = 5; - public GreenEnemy(int x, int y) : base(x, y) + public GreenShipTypeA(int x, int y) : base(x, y) { BoundBox = new Rectangle(0, 0, 64, 64); YVelocity = 1; diff --git a/AlientAttack.MonoGame/Things/Enemies/RedEnemy.cs b/AlientAttack.MonoGame/Things/Enemies/Ships/TypeA/RedShipTypeA.cs similarity index 94% rename from AlientAttack.MonoGame/Things/Enemies/RedEnemy.cs rename to AlientAttack.MonoGame/Things/Enemies/Ships/TypeA/RedShipTypeA.cs index 562b892..58d9947 100644 --- a/AlientAttack.MonoGame/Things/Enemies/RedEnemy.cs +++ b/AlientAttack.MonoGame/Things/Enemies/Ships/TypeA/RedShipTypeA.cs @@ -2,15 +2,15 @@ using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; -namespace AlienAttack.MonoGame.Things.Enemies; +namespace AlienAttack.MonoGame.Things.Enemies.Ships.TypeA; -public class RedEnemy : EnemyShip +public class RedShipTypeA : ShipTypeA { protected int FireThreshold => 20; protected int CurrentFireThreshold { get; set; } = 20; protected override int Health { get; set; } = 5; - public RedEnemy(int x, int y) : base(x, y) + public RedShipTypeA(int x, int y) : base(x, y) { BoundBox = new Rectangle(0, 0, 64, 64); YVelocity = 1.5f; diff --git a/AlientAttack.MonoGame/Things/Enemies/Ships/TypeA/ShipTypeA.cs b/AlientAttack.MonoGame/Things/Enemies/Ships/TypeA/ShipTypeA.cs new file mode 100644 index 0000000..3994ff2 --- /dev/null +++ b/AlientAttack.MonoGame/Things/Enemies/Ships/TypeA/ShipTypeA.cs @@ -0,0 +1,18 @@ +using AlienAttack.MonoGame.Things.Muzzles; +using Microsoft.Xna.Framework; + +namespace AlienAttack.MonoGame.Things.Enemies.Ships.TypeA; + +public abstract class ShipTypeA(int x, int y) : EnemyShip(x, y) +{ + public override Vector2 GetMuzzleLocal(MuzzleId muzzle) + { + return muzzle switch + { + MuzzleId.Left => new(20, 49), + MuzzleId.Center => new(31.5f, 49), + MuzzleId.Right => new(43, 49), + _ => new(), + }; + } +} \ No newline at end of file diff --git a/AlientAttack.MonoGame/Things/Enemies/TealEnemy.cs b/AlientAttack.MonoGame/Things/Enemies/Ships/TypeA/TealShipTypeA.cs similarity index 94% rename from AlientAttack.MonoGame/Things/Enemies/TealEnemy.cs rename to AlientAttack.MonoGame/Things/Enemies/Ships/TypeA/TealShipTypeA.cs index 62b095f..bde8fce 100644 --- a/AlientAttack.MonoGame/Things/Enemies/TealEnemy.cs +++ b/AlientAttack.MonoGame/Things/Enemies/Ships/TypeA/TealShipTypeA.cs @@ -2,15 +2,15 @@ using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; -namespace AlienAttack.MonoGame.Things.Enemies; +namespace AlienAttack.MonoGame.Things.Enemies.Ships.TypeA; -public class TealEnemy : EnemyShip +public class TealShipTypeA : ShipTypeA { protected int FireThreshold => 20; protected int CurrentFireThreshold { get; set; } = 20; protected override int Health { get; set; } = 5; - public TealEnemy(int x, int y) : base(x, y) + public TealShipTypeA(int x, int y) : base(x, y) { BoundBox = new Rectangle(0, 0, 64, 64); YVelocity = 1; diff --git a/AlientAttack.MonoGame/Things/Enemies/Enemy02Green.cs b/AlientAttack.MonoGame/Things/Enemies/Ships/TypeB/GreenShipTypeB.cs similarity index 93% rename from AlientAttack.MonoGame/Things/Enemies/Enemy02Green.cs rename to AlientAttack.MonoGame/Things/Enemies/Ships/TypeB/GreenShipTypeB.cs index f56235a..229f0ad 100644 --- a/AlientAttack.MonoGame/Things/Enemies/Enemy02Green.cs +++ b/AlientAttack.MonoGame/Things/Enemies/Ships/TypeB/GreenShipTypeB.cs @@ -1,10 +1,9 @@ using AlienAttack.MonoGame.Things.Bullets; -using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; -namespace AlienAttack.MonoGame.Things.Enemies; +namespace AlienAttack.MonoGame.Things.Enemies.Ships.TypeB; -public class Enemy02Green : EnemyShip +public class GreenShipTypeB : ShipTypeB { public const int Width = 64; public const int Height = 64; @@ -13,7 +12,7 @@ public class Enemy02Green : EnemyShip protected int CurrentFireThreshold { get; set; } = 20; protected override int Health { get; set; } = 5; - public Enemy02Green(int x, int y) : base(x, y) + public GreenShipTypeB(int x, int y) : base(x, y) { BoundBox = new(0, 0, Width, Height); YVelocity = 2; diff --git a/AlientAttack.MonoGame/Things/Enemies/Enemy02Red.cs b/AlientAttack.MonoGame/Things/Enemies/Ships/TypeB/RedShipTypeB.cs similarity index 93% rename from AlientAttack.MonoGame/Things/Enemies/Enemy02Red.cs rename to AlientAttack.MonoGame/Things/Enemies/Ships/TypeB/RedShipTypeB.cs index ce3542a..51e1ce9 100644 --- a/AlientAttack.MonoGame/Things/Enemies/Enemy02Red.cs +++ b/AlientAttack.MonoGame/Things/Enemies/Ships/TypeB/RedShipTypeB.cs @@ -1,10 +1,9 @@ using AlienAttack.MonoGame.Things.Bullets; -using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; -namespace AlienAttack.MonoGame.Things.Enemies; +namespace AlienAttack.MonoGame.Things.Enemies.Ships.TypeB; -public class Enemy02Red : EnemyShip +public class RedShipTypeB : ShipTypeB { public const int Width = 64; public const int Height = 64; @@ -13,7 +12,7 @@ public class Enemy02Red : EnemyShip protected int CurrentFireThreshold { get; set; } = 20; protected override int Health { get; set; } = 5; - public Enemy02Red(int x, int y) : base(x, y) + public RedShipTypeB(int x, int y) : base(x, y) { BoundBox = new(0, 0, Width, Height); YVelocity = 3; diff --git a/AlientAttack.MonoGame/Things/Enemies/Ships/TypeB/ShipTypeB.cs b/AlientAttack.MonoGame/Things/Enemies/Ships/TypeB/ShipTypeB.cs new file mode 100644 index 0000000..ef1582e --- /dev/null +++ b/AlientAttack.MonoGame/Things/Enemies/Ships/TypeB/ShipTypeB.cs @@ -0,0 +1,19 @@ +using AlienAttack.MonoGame.Things.Muzzles; +using Microsoft.Xna.Framework; + +namespace AlienAttack.MonoGame.Things.Enemies.Ships.TypeB; + +public abstract class ShipTypeB(int x, int y) : EnemyShip(x, y) +{ + // TODO + public override Vector2 GetMuzzleLocal(MuzzleId muzzle) + { + return muzzle switch + { + MuzzleId.Left => new(20, 49), + MuzzleId.Center => new(31.5f, 49), + MuzzleId.Right => new(43, 49), + _ => new(), + }; + } +} \ No newline at end of file diff --git a/AlientAttack.MonoGame/Things/Enemies/Enemy02Teal.cs b/AlientAttack.MonoGame/Things/Enemies/Ships/TypeB/TealShipTypeB.cs similarity index 93% rename from AlientAttack.MonoGame/Things/Enemies/Enemy02Teal.cs rename to AlientAttack.MonoGame/Things/Enemies/Ships/TypeB/TealShipTypeB.cs index b1b7eb0..2679c08 100644 --- a/AlientAttack.MonoGame/Things/Enemies/Enemy02Teal.cs +++ b/AlientAttack.MonoGame/Things/Enemies/Ships/TypeB/TealShipTypeB.cs @@ -1,10 +1,9 @@ using AlienAttack.MonoGame.Things.Bullets; -using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; -namespace AlienAttack.MonoGame.Things.Enemies; +namespace AlienAttack.MonoGame.Things.Enemies.Ships.TypeB; -public class Enemy02Teal : EnemyShip +public class TealShipTypeB : ShipTypeB { public const int Width = 64; public const int Height = 64; @@ -13,7 +12,7 @@ public class Enemy02Teal : EnemyShip protected int CurrentFireThreshold { get; set; } = 20; protected override int Health { get; set; } = 5; - public Enemy02Teal(int x, int y) : base(x, y) + public TealShipTypeB(int x, int y) : base(x, y) { BoundBox = new(0, 0, Width, Height); YVelocity = 1; diff --git a/AlientAttack.MonoGame/Things/Player.cs b/AlientAttack.MonoGame/Things/Player.cs index b4fb4b5..27b1ce3 100644 --- a/AlientAttack.MonoGame/Things/Player.cs +++ b/AlientAttack.MonoGame/Things/Player.cs @@ -1,5 +1,5 @@ using AlienAttack.MonoGame.Things.Bullets; -using AlienAttack.MonoGame.Things.Enemies; +using AlienAttack.MonoGame.Things.Enemies.Ships; using AlienAttack.MonoGame.Things.Items; using AlienAttack.MonoGame.Things.Muzzles; using AlienAttack.MonoGame.Things.Weapons; @@ -415,15 +415,6 @@ public class Player : MoveableSprite if (context.Sprite is Shields) { - //SCIEnrg_Shield Activate_01_SFRMS_SCIWPNS - - //int number = context.Random.Next(1, 6); - - //SoundEffect soundEffect = context.Content.Load(@$"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); }