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; } } }