using System;
using ActiveProtect.SimulationEnvironment;
using Model;
namespace ActiveProtect.Models
{
///
/// 表示仿真中的导弹
///
public class MissileBase : SimulationElement
{
///
/// 导弹类型
///
public MissileType Type { get; protected set; }
///
/// 当前速度(米/秒)
///
public double Speed { get; protected set; }
///
/// 最大速度(米/秒)
///
public double MaxSpeed { get; protected set; }
///
/// 目标ID
///
public string TargetId { get; protected set; }
///
/// 最大飞行时间(秒)
///
public double MaxFlightTime { get; protected set; }
///
/// 最大飞行距离(米)
///
public double MaxFlightDistance { get; protected set; }
///
/// 当前飞行时间(秒)
///
public double FlightTime { get; protected set; }
///
/// 当前飞行距离(米)
///
public double FlightDistance { get; protected set; }
///
/// 与目标的距离(米)
///
public double DistanceToTarget { get; protected set; }
///
/// 导弹距离参数
///
public MissileDistanceParams DistanceParams { get; protected set; }
///
/// 飞行阶段配置
///
public FlightStageConfig StageConfig { get; protected set; }
///
/// 当前飞行阶段
///
public FlightStage CurrentStage { get; protected set; }
///
/// 上一帧目标位置
///
private Vector3D LastTargetPosition;
///
/// 比例导引系数
///
private const double N = 3;
///
/// 推力加速度(米/秒²)
///
public double ThrustAcceleration { get; protected set; }
///
/// 当前发动机燃烧时间(秒)
///
public double EngineBurnTime { get; protected set; }
///
/// 最大发动机燃烧时间(秒)
///
public double MaxEngineBurnTime { get; protected set; }
///
/// 最大加速度(米/秒²)
///
public double MaxAcceleration { get; protected set; } = 100;
///
/// 比例导引系数
///
public double ProportionalNavigationCoefficient { get; set; }
///
/// 是否有制导
///
public bool HasGuidance { get; protected set; } = false;
///
/// 失去制导的时间(秒)
///
protected double LostGuidanceTime { get; set; } = 0;
///
/// 最后已知的速度向量
///
protected Vector3D LastKnownVelocity = Vector3D.Zero;
///
/// 发射速度(米/秒)
///
public const double LAUNCH_SPEED = 10;
///
/// 发射阶段持续时间(秒)
///
public const double LAUNCH_DURATION = 0.5;
protected IMissileStageStrategy currentStage;
private Dictionary stageStrategies;
///
/// 导弹质量(千克)
///
public double Mass { get; protected set; } = 100;
///
/// 构造函数
///
public MissileBase(string id, MissileConfig missileConfig, ISimulationManager simulationManager)
: base(id, missileConfig.InitialPosition, missileConfig.InitialOrientation, simulationManager)
{
// 初始化导弹属性
Speed = missileConfig.InitialSpeed;
MaxSpeed = missileConfig.MaxSpeed;
MaxFlightTime = missileConfig.MaxFlightTime;
MaxFlightDistance = missileConfig.MaxFlightDistance;
DistanceParams = missileConfig.DistanceParams;
StageConfig = missileConfig.StageConfig;
IsActive = true;
FlightTime = 0;
FlightDistance = 0;
SimulationManager = simulationManager;
ThrustAcceleration = missileConfig.ThrustAcceleration;
EngineBurnTime = 0;
MaxEngineBurnTime = missileConfig.MaxEngineBurnTime;
MaxAcceleration = missileConfig.MaxAcceleration;
ProportionalNavigationCoefficient = missileConfig.ProportionalNavigationCoefficient;
TargetId = $"Tank_{missileConfig.TargetIndex + 1}";
Vector3D horizontalDirection = new Vector3D(Orientation.ToVector().X, 0, Orientation.ToVector().Z).Normalize();
Velocity = horizontalDirection * missileConfig.InitialSpeed;
// 初始化策略字典
stageStrategies = new Dictionary
{
{ FlightStage.Launch, new LaunchStageStrategy(this) },
{ FlightStage.Acceleration, new AccelerationStageStrategy(this) },
{ FlightStage.Cruise, new CruiseStageStrategy(this) },
{ FlightStage.TerminalGuidance, new TerminalGuidanceStageStrategy(this) },
{ FlightStage.Attack, new AttackStageStrategy(this) }
};
// 设置初始阶段
SetInitialStage();
currentStage = stageStrategies[CurrentStage];
LastTargetPosition = Position;
DistanceToTarget = Vector3D.Distance(Position, SimulationManager.GetEntityById(TargetId).Position);
}
///
/// 设置导弹的初始飞行阶段
///
private void SetInitialStage()
{
if (StageConfig.EnableLaunch) CurrentStage = FlightStage.Launch;
else if (StageConfig.EnableAcceleration) CurrentStage = FlightStage.Acceleration;
else if (StageConfig.EnableCruise) CurrentStage = FlightStage.Cruise;
else if (StageConfig.EnableTerminalGuidance) CurrentStage = FlightStage.TerminalGuidance;
else if (StageConfig.EnableAttack) CurrentStage = FlightStage.Attack;
Console.WriteLine($"导弹 {Id} 的初始阶段: {CurrentStage}");
}
///
/// 更新导弹状态
///
public override void Update(double deltaTime)
{
if (!IsActive) return;
if (ShouldSelfDestruct())
{
SelfDestruct();
return;
}
UpdateEngineBurnTime(deltaTime);
Vector3D guidanceCommand = GetGuidanceCommand();
UpdateMotionState(deltaTime, guidanceCommand);
if (CheckHit())
{
Explode();
return;
}
currentStage.Update(deltaTime);
}
protected virtual Vector3D GetGuidanceCommand()
{
throw new NotImplementedException();
}
private void UpdateMotionState(double deltaTime, Vector3D guidanceCommand)
{
Vector3D acceleration = CalculateAcceleration(Velocity, guidanceCommand);
// 使用四阶龙格-库塔方法更新导弹的位置和速度
(Position, Velocity) = BasicGuidanceSystem.RungeKutta4(deltaTime, Position, Velocity, acceleration);
// 限制速度不超过最大速度
if (Velocity.Magnitude() > MaxSpeed)
{
Velocity = Velocity.Normalize() * MaxSpeed;
}
UpdateMotionStatus(deltaTime);
}
protected virtual void UpdateMotionStatus(double deltaTime)
{
Speed = Velocity.Magnitude();
Orientation = Orientation.FromVector(Velocity);
FlightTime += deltaTime;
FlightDistance += Speed * deltaTime;
DistanceToTarget = Vector3D.Distance(Position, SimulationManager.GetEntityById(TargetId).Position);
}
///
/// 计算导弹的加速度
///
private Vector3D CalculateAcceleration(Vector3D velocity, Vector3D guidanceCommand)
{
Vector3D thrustAcceleration = Vector3D.Zero;
Vector3D guidanceAcceleration = Vector3D.Zero;
switch (CurrentStage)
{
case FlightStage.Launch:
thrustAcceleration = Orientation.ToVector() * ThrustAcceleration;
break;
case FlightStage.Acceleration:
thrustAcceleration = Orientation.ToVector() * ThrustAcceleration;
guidanceAcceleration = guidanceCommand;
break;
case FlightStage.Cruise:
thrustAcceleration = Orientation.ToVector() * (ThrustAcceleration * 0.1);
guidanceAcceleration = guidanceCommand * 1;
break;
case FlightStage.TerminalGuidance:
thrustAcceleration = Orientation.ToVector() * (ThrustAcceleration * 0.2);
guidanceAcceleration = guidanceCommand * 1.2;
break;
case FlightStage.Attack:
thrustAcceleration = Orientation.ToVector() * ThrustAcceleration;
guidanceAcceleration = guidanceCommand * 1.5;
break;
}
if (!HasGuidance)
{
if (velocity.Magnitude() > 0)
{
thrustAcceleration = velocity.Normalize() * ThrustAcceleration;
}
else
{
thrustAcceleration = Orientation.ToVector() * ThrustAcceleration;
}
}
// 计算空气阻力的影响
Vector3D dragAcceleration = velocity.Normalize() * -1 * CalculateDrag(velocity.Magnitude()) / Mass;
Vector3D totalAcceleration = guidanceAcceleration + thrustAcceleration + dragAcceleration;
//Console.WriteLine($"导弹 {Id} 的加速度: {totalAcceleration}, 制导加速度: {guidanceAcceleration}, 推力加速度: {thrustAcceleration}, 空气阻力加速度: {dragAcceleration}");
if (totalAcceleration.Magnitude() > MaxAcceleration)
{
totalAcceleration = totalAcceleration.Normalize() * MaxAcceleration;
}
return totalAcceleration;
}
///
/// 切换导弹飞行阶段
///
public void ChangeStage(FlightStage newStage)
{
if (stageStrategies.TryGetValue(newStage, out var strategy))
{
if (IsStageEnabled(newStage))
{
CurrentStage = newStage;
currentStage = strategy;
Console.WriteLine($"导弹 {Id} 切换到 {newStage} 阶段");
}
else
{
// 如果目标阶段不可用,尝试切换到下一个可用阶段
TryChangeToNextAvailableStage(newStage);
}
}
else
{
Console.WriteLine($"导弹 {Id} 无法切换到未知阶段 {newStage}");
}
}
///
/// 检查指定飞行阶段是否启用
///
private bool IsStageEnabled(FlightStage stage)
{
return stage switch
{
FlightStage.Launch => StageConfig.EnableLaunch,
FlightStage.Acceleration => StageConfig.EnableAcceleration,
FlightStage.Cruise => StageConfig.EnableCruise,
FlightStage.TerminalGuidance => StageConfig.EnableTerminalGuidance,
FlightStage.Attack => StageConfig.EnableAttack,
_ => false
};
}
///
/// 尝试切换到下一个可用的飞行阶段
///
private void TryChangeToNextAvailableStage(FlightStage startStage)
{
FlightStage[] stageOrder = [FlightStage.Launch, FlightStage.Acceleration, FlightStage.Cruise, FlightStage.TerminalGuidance, FlightStage.Attack];
int startIndex = Array.IndexOf(stageOrder, startStage);
for (int i = startIndex + 1; i < stageOrder.Length; i++)
{
if (IsStageEnabled(stageOrder[i]))
{
ChangeStage(stageOrder[i]);
return;
}
}
// 如果没有可用的下一个阶段,导弹自毁
Console.WriteLine($"导弹 {Id} 没有可用的下一个阶段,准备自毁");
SelfDestruct();
}
///
/// 计算导弹的加速度
///
private (Vector3D, Vector3D) CalculateDerivatives_RK4(Vector3D position, Vector3D velocity, double deltaTime)
{
Vector3D guidanceAcceleration = Vector3D.Zero;
Vector3D thrustAcceleration = Vector3D.Zero;
switch (CurrentStage)
{
case FlightStage.Launch:
thrustAcceleration = Orientation.ToVector() * ThrustAcceleration;
break;
case FlightStage.Acceleration:
thrustAcceleration = Orientation.ToVector() * ThrustAcceleration;
guidanceAcceleration = CalculateProportionalNavigation(position);
break;
case FlightStage.Cruise:
thrustAcceleration = Orientation.ToVector() * (ThrustAcceleration * 0.1);
guidanceAcceleration = CalculateProportionalNavigation(position) * 0.5;
break;
case FlightStage.TerminalGuidance:
thrustAcceleration = Orientation.ToVector() * (ThrustAcceleration * 0.1);
guidanceAcceleration = CalculateProportionalNavigation(position) * 1.5;
break;
case FlightStage.Attack:
thrustAcceleration = Orientation.ToVector() * ThrustAcceleration;
guidanceAcceleration = CalculateProportionalNavigation(position) * 2;
break;
}
if (!HasGuidance)
{
guidanceAcceleration = Vector3D.Zero;
if (velocity.Magnitude() > 0)
{
thrustAcceleration = velocity.Normalize() * ThrustAcceleration;
}
else
{
thrustAcceleration = Orientation.ToVector() * ThrustAcceleration;
}
}
// 计算空气阻力的影响
Vector3D dragAcceleration = velocity.Normalize() * -1 * CalculateDrag(velocity.Magnitude()) / Mass;
// 计算重力加速度
Vector3D gravityCompensation = new(0, 9.81, 0);
Vector3D gravityAcceleration = new(0, -9.81, 0);
Vector3D totalAcceleration = guidanceAcceleration + thrustAcceleration + gravityCompensation + gravityAcceleration + dragAcceleration;
if (totalAcceleration.Magnitude() > MaxAcceleration)
{
totalAcceleration = totalAcceleration.Normalize() * MaxAcceleration;
}
return (velocity, totalAcceleration);
}
///
/// 计算空气阻力
///
private static double CalculateDrag(double speed)
{
const double dragCoefficient = 0.1; // 减小阻力系数
const double airDensity = 1.225; // 海平面空气密度,kg/m^3
const double referenceArea = 0.01; // 减小导弹的参考面积,m^2
return 0.5 * dragCoefficient * airDensity * referenceArea * speed * speed;
}
///
/// 使用 Runge-Kutta 方法更新位置和速度
///
// private (Vector3D, Vector3D) UpdatePositionAndVelocityRK4(double deltaTime)
// {
// Vector3D k1, k2, k3, k4;
// Vector3D v1, v2, v3, v4;
// (k1, v1) = CalculateDerivatives(Position, Velocity, deltaTime);
// (k2, v2) = CalculateDerivatives(Position + k1 * (deltaTime / 2), Velocity + v1 * (deltaTime / 2), deltaTime / 2);
// (k3, v3) = CalculateDerivatives(Position + k2 * (deltaTime / 2), Velocity + v2 * (deltaTime / 2), deltaTime / 2);
// (k4, v4) = CalculateDerivatives(Position + k3 * deltaTime, Velocity + v3 * deltaTime, deltaTime);
// Vector3D newPosition = Position + (k1 + k2 * 2 + k3 * 2 + k4) * (deltaTime / 6);
// Vector3D newVelocity = Velocity + (v1 + v2 * 2 + v3 * 2 + v4) * (deltaTime / 6);
// // 限制速度不超过最大速度
// if (newVelocity.Magnitude() > MaxSpeed)
// {
// newVelocity = newVelocity.Normalize() * MaxSpeed;
// }
// return (newPosition, newVelocity);
// }
///
/// 检查是否命中目标
///
protected bool CheckHit()
{
return DistanceToTarget <= DistanceParams.ExplosionDistance;
}
///
/// 检查是否应该自毁
///
protected bool ShouldSelfDestruct()
{
if (FlightTime >= MaxFlightTime)
{
Console.WriteLine($"导弹 {Id} 超出最大飞行时间 ({FlightTime:F2}/{MaxFlightTime:F2}),准备自毁");
return true;
}
if (FlightDistance >= MaxFlightDistance)
{
Console.WriteLine($"导弹 {Id} 超出最大飞行距离 ({FlightDistance:F2}/{MaxFlightDistance:F2}),准备自毁");
return true;
}
if (Position.Y <= -1.0) // 数字略小于0
{
Console.WriteLine($"导弹 {Id} 高度小于等于0 ({Position.Y:F2}),准备自毁");
return true;
}
return false;
}
///
/// 更新发动机燃烧时间
///
private void UpdateEngineBurnTime(double deltaTime)
{
if (CurrentStage == FlightStage.Acceleration && EngineBurnTime < MaxEngineBurnTime)
{
EngineBurnTime += deltaTime;
}
}
///
/// 计算比例导引加速度
///
private Vector3D CalculateProportionalNavigation(Vector3D position)
{
Vector3D targetPosition = SimulationManager.GetEntityById(TargetId).Position;
Vector3D LOS = targetPosition - position;
Vector3D LOSRate = (targetPosition - LastTargetPosition) / FlightTime - Velocity;
LastTargetPosition = targetPosition;
return Vector3D.CrossProduct(Vector3D.CrossProduct(LOS, LOSRate), LOS).Normalize()
* ProportionalNavigationCoefficient * Velocity.Magnitude();
}
///
/// 导弹爆炸
///
public void Explode()
{
Deactivate();
SimulationManager.HandleTargetHit(TargetId, Id);
Console.WriteLine($"导弹 {Id} 在 {Position} 爆炸,命中目标!");
}
///
/// 导弹自毁
///
public void SelfDestruct()
{
if (IsActive)
{
string reason = FlightTime >= MaxFlightTime ? "超出最大飞行时间" :
FlightDistance >= MaxFlightDistance ? "超出最大飞行距离" :
Position.Y <= 0 ? "高度小于等于0" :
!HasGuidance ? "失去引导" : "未知原因";
Console.WriteLine($"导弹 {Id} 自毁。原因: {reason}");
Deactivate();
}
}
///
/// 设置比例导引系数
///
public void SetProportionalNavigationCoefficient(double newCoefficient)
{
ProportionalNavigationCoefficient = newCoefficient;
Console.WriteLine($"导弹 {Id} 的比例导引系数已更新为 {newCoefficient}");
}
///
/// 获取导弹状态
///
public override string GetStatus()
{
MissileRunningState missileRunningState = GetState();
return $"导弹 {missileRunningState.Id}:\n" +
$" 位置: {missileRunningState.Position}\n" +
$" 速度: {missileRunningState.Speed:F2} m/s\n" +
$" 当前状态: {missileRunningState.CurrentStage}\n" +
$" 飞行时间: {missileRunningState.FlightTime:F2}/{MaxFlightTime:F2}\n" +
$" 飞行距离: {missileRunningState.FlightDistance:F2}/{MaxFlightDistance:F2}\n" +
$" 距离目标: {missileRunningState.DistanceToTarget:F2}\n" +
$" 发动机工作时间: {missileRunningState.EngineBurnTime:F2}/{MaxEngineBurnTime:F2}\n" +
$" 有引导: {(missileRunningState.HasGuidance ? "是" : "否")}\n" +
$" 失去引导时间: {missileRunningState.LostGuidanceTime:F2}";
}
///
/// 更新导弹的制导状态
///
protected virtual void UpdateGuidanceStatus()
{
// 基类中的默认实现
}
public MissileRunningState GetState()
{
return new MissileRunningState
{
Id = Id,
Type = Type,
Position = Position,
Velocity = Velocity,
Orientation = Orientation,
Speed = Speed,
TargetId = TargetId,
FlightTime = FlightTime,
FlightDistance = FlightDistance,
DistanceToTarget = DistanceToTarget,
CurrentStage = CurrentStage,
HasGuidance = HasGuidance,
LostGuidanceTime = LostGuidanceTime,
EngineBurnTime = EngineBurnTime,
IsActive = IsActive
};
}
}
///
/// 导弹飞行阶段策略接口
///
public interface IMissileStageStrategy
{
void Update(double deltaTime);
}
///
/// 发射阶段策略
///
public class LaunchStageStrategy : IMissileStageStrategy
{
private readonly MissileBase missile;
private double launchTime = 0;
public LaunchStageStrategy(MissileBase missile)
{
this.missile = missile;
}
public void Update(double deltaTime)
{
launchTime += deltaTime;
if (launchTime >= MissileBase.LAUNCH_DURATION || missile.Speed >= missile.MaxSpeed * 0.1)
{
missile.ChangeStage(FlightStage.Acceleration);
}
}
}
///
/// 加速阶段策略
///
public class AccelerationStageStrategy(MissileBase missile) : IMissileStageStrategy
{
private readonly MissileBase missile = missile;
public void Update(double deltaTime)
{
if (missile.EngineBurnTime >= missile.MaxEngineBurnTime || missile.Speed >= missile.MaxSpeed)
{
missile.ChangeStage(FlightStage.Cruise);
}
}
}
///
/// 巡航阶段策略
///
public class CruiseStageStrategy(MissileBase missile) : IMissileStageStrategy
{
private readonly MissileBase missile = missile;
public void Update(double deltaTime)
{
if (missile.DistanceToTarget <= missile.DistanceParams.TerminalGuidanceDistance)
{
missile.ChangeStage(FlightStage.TerminalGuidance);
}
}
}
///
/// 终端制导阶段策略
///
public class TerminalGuidanceStageStrategy(MissileBase missile) : IMissileStageStrategy
{
private readonly MissileBase missile = missile;
public void Update(double deltaTime)
{
if (missile.DistanceToTarget <= missile.DistanceParams.AttackDistance)
{
missile.ChangeStage(FlightStage.Attack);
}
}
}
///
/// 攻击阶段策略
///
public class AttackStageStrategy(MissileBase missile) : IMissileStageStrategy
{
private readonly MissileBase missile = missile;
public void Update(double deltaTime)
{
if (missile.DistanceToTarget <= missile.DistanceParams.ExplosionDistance)
{
missile.Explode();
}
}
}
///
/// 无制导阶段策略
///
public class UnguidedStageStrategy(MissileBase missile) : IMissileStageStrategy
{
private readonly MissileBase missile = missile;
public void Update(double deltaTime)
{
// 检查是否重新获得引导
if (missile.HasGuidance)
{
Console.WriteLine($"导弹 {missile.Id} 重新获得引导,退出无制导阶段");
if (missile.DistanceToTarget <= missile.DistanceParams.AttackDistance)
{
missile.ChangeStage(FlightStage.Attack);
}
else if (missile.DistanceToTarget <= missile.DistanceParams.TerminalGuidanceDistance)
{
missile.ChangeStage(FlightStage.TerminalGuidance);
}
else
{
missile.ChangeStage(FlightStage.Cruise);
}
}
}
}
///
/// 表示导弹的当前状态
///
public struct MissileRunningState
{
///
/// 导弹ID
///
public string Id { get; set; }
///
/// 导弹类型
///
public MissileType Type { get; set; }
///
/// 当前位置
///
public Vector3D Position { get; set; }
///
/// 当前速度向量
///
public Vector3D Velocity { get; set; }
///
/// 当前朝向
///
public Orientation Orientation { get; set; }
///
/// 当前速度(米/秒)
///
public double Speed { get; set; }
///
/// 目标ID
///
public string TargetId { get; set; }
///
/// 当前飞行时间(秒)
///
public double FlightTime { get; set; }
///
/// 当前飞行距离(米)
///
public double FlightDistance { get; set; }
///
/// 与目标的距离(米)
///
public double DistanceToTarget { get; set; }
///
/// 当前飞行阶段
///
public FlightStage CurrentStage { get; set; }
///
/// 是否有制导
///
public bool HasGuidance { get; set; }
///
/// 失去制导时间(秒)
///
public double LostGuidanceTime { get; set; }
///
/// 当前发动机燃烧时间(秒)
///
public double EngineBurnTime { get; set; }
///
/// 是否处于活动状态
///
public bool IsActive { get; set; }
}
}