98 lines
2.9 KiB
C#
98 lines
2.9 KiB
C#
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;
|
|
}
|
|
} |