352 lines
12 KiB
C#
352 lines
12 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using ActiveProtect.Simulation;
|
||
using ActiveProtect.Utility;
|
||
|
||
namespace ActiveProtect.Models
|
||
{
|
||
|
||
/// <summary>
|
||
/// 表示仿真中的导弹
|
||
/// </summary>
|
||
public class MissileBase : SimulationElement
|
||
{
|
||
/// <summary>
|
||
/// 当前飞行时间(秒)
|
||
/// </summary>
|
||
public double FlightTime { get; protected set; }
|
||
|
||
/// <summary>
|
||
/// 当前飞行距离(米)
|
||
/// </summary>
|
||
public double FlightDistance { get; protected set; }
|
||
|
||
/// <summary>
|
||
/// 当前发动机燃烧时间(秒)
|
||
/// </summary>
|
||
public double EngineBurnTime { get; protected set; }
|
||
|
||
/// <summary>
|
||
/// 是否有制导
|
||
/// </summary>
|
||
public bool HasGuidance { get; protected set; }
|
||
|
||
/// <summary>
|
||
/// 失去制导的时间(秒)
|
||
/// </summary>
|
||
protected double LostGuidanceTime { get; set; } = 0;
|
||
|
||
/// <summary>
|
||
/// 最后已知的速度向量
|
||
/// </summary>
|
||
protected Vector3D LastKnownVelocity = Vector3D.Zero;
|
||
|
||
/// <summary>
|
||
/// 制导加速度
|
||
/// </summary>
|
||
protected Vector3D GuidanceAcceleration { get; set; }
|
||
|
||
/// <summary>
|
||
/// 推力加速度
|
||
/// </summary>
|
||
protected Vector3D ThrustAcceleration { get; set; }
|
||
|
||
/// <summary>
|
||
/// 导弹固定配置参数
|
||
/// </summary>
|
||
public readonly MissileProperties MissileProperties;
|
||
|
||
/// <summary>
|
||
/// 构造函数
|
||
/// </summary>
|
||
public MissileBase(MissileProperties properties, ISimulationManager manager)
|
||
: base(properties.Id, properties.InitialPosition, properties.InitialOrientation, properties.InitialSpeed, manager)
|
||
{
|
||
MissileProperties = properties;
|
||
SimulationManager = manager;
|
||
|
||
IsActive = false;
|
||
HasGuidance = false;
|
||
FlightTime = 0;
|
||
FlightDistance = 0;
|
||
EngineBurnTime = 0;
|
||
GuidanceAcceleration = Vector3D.Zero;
|
||
ThrustAcceleration = Vector3D.Zero;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新导弹状态
|
||
/// </summary>
|
||
public override void Update(double deltaTime)
|
||
{
|
||
if (IsActive)
|
||
{
|
||
// 更新导弹运动状态
|
||
UpdateMotionState(deltaTime);
|
||
}
|
||
}
|
||
|
||
protected virtual void UpdateMotionState(double deltaTime)
|
||
{
|
||
|
||
//Vector3D acceleration = CalculateAcceleration(Velocity);
|
||
|
||
Vector3D acceleration = GuidanceAcceleration;
|
||
|
||
if (HasGuidance)
|
||
{
|
||
// 制导条件下,使用四阶龙格-库塔方法更新导弹的位置和速度
|
||
(Position, Velocity) = MotionAlgorithm.RungeKutta4(deltaTime, Position, Velocity, acceleration);
|
||
}
|
||
else
|
||
{
|
||
// 无制导条件下,使用运动学方程更新导弹的位置和速度
|
||
(Position, Velocity) = MotionAlgorithm.CalculateBallisticMotion(Position, Velocity, acceleration, deltaTime);
|
||
}
|
||
|
||
|
||
|
||
// 限制速度不超过最大速度
|
||
if (Velocity.Magnitude() > MissileProperties.MaxSpeed)
|
||
{
|
||
Velocity = Velocity.Normalize() * MissileProperties.MaxSpeed;
|
||
}
|
||
|
||
Speed = Velocity.Magnitude();
|
||
Orientation = Orientation.FromVector(Velocity);
|
||
|
||
// 添加高斯噪声(测试用,用于测试运动中概率的影响)
|
||
// Position = MotionAlgorithm.AddRandomPerturbation(Position);
|
||
// Velocity = MotionAlgorithm.AddRandomPerturbation(Velocity);
|
||
|
||
FlightTime += deltaTime;
|
||
FlightDistance += Speed * deltaTime;
|
||
//DistanceToTarget = Vector3D.Distance(Position, SimulationManager.GetEntityById(MissileProperties.TargetId).Position);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 计算导弹的加速度
|
||
/// </summary>
|
||
private Vector3D CalculateAcceleration(Vector3D velocity)
|
||
{
|
||
// 计算空气阻力的影响
|
||
Vector3D dragAcceleration = velocity.Normalize() * -1 * CalculateDrag(velocity.Magnitude()) / MissileProperties.Mass;
|
||
|
||
Vector3D totalAcceleration = GuidanceAcceleration + ThrustAcceleration + dragAcceleration;
|
||
|
||
Console.WriteLine($"导弹 {Id} 的加速度: {totalAcceleration}, 制导加速度: {GuidanceAcceleration}, 推力加速度: {ThrustAcceleration}, 空气阻力加速度: {dragAcceleration}");
|
||
if (totalAcceleration.Magnitude() > MissileProperties.MaxAcceleration)
|
||
{
|
||
totalAcceleration = totalAcceleration.Normalize() * MissileProperties.MaxAcceleration;
|
||
}
|
||
|
||
return totalAcceleration;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 计算空气阻力
|
||
/// </summary>
|
||
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;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 检查是否应该自毁
|
||
/// </summary>
|
||
protected bool ShouldSelfDestruct()
|
||
{
|
||
if (FlightTime >= MissileProperties.MaxFlightTime)
|
||
{
|
||
Console.WriteLine($"导弹 {Id} 超出最大飞行时间 ({FlightTime:F2}/{MissileProperties.MaxFlightTime:F2}),准备自毁");
|
||
return true;
|
||
}
|
||
if (FlightDistance >= MissileProperties.MaxFlightDistance)
|
||
{
|
||
Console.WriteLine($"导弹 {Id} 超出最大飞行距离 ({FlightDistance:F2}/{MissileProperties.MaxFlightDistance:F2}),准备自毁");
|
||
return true;
|
||
}
|
||
if (Position.Y <= -1.0) // 数字略小于0
|
||
{
|
||
Console.WriteLine($"导弹 {Id} 高度小于等于0 ({Position.Y:F2}),准备自毁");
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新发动机燃烧时间
|
||
/// </summary>
|
||
// private void UpdateEngineBurnTime(double deltaTime)
|
||
// {
|
||
// if (CurrentStage == FlightStage.Acceleration && EngineBurnTime < MaxEngineBurnTime)
|
||
// {
|
||
// EngineBurnTime += deltaTime;
|
||
// }
|
||
// }
|
||
|
||
/// <summary>
|
||
/// 导弹爆炸
|
||
/// </summary>
|
||
protected virtual void Explode()
|
||
{
|
||
Deactivate();
|
||
}
|
||
|
||
public override void Activate()
|
||
{
|
||
base.Activate();
|
||
SimulationManager.SubscribeToEvent<TargetHitEvent>(OnTargetHitEvent);
|
||
}
|
||
|
||
public override void Deactivate()
|
||
{
|
||
base.Deactivate();
|
||
SimulationManager.UnsubscribeFromEvent<TargetHitEvent>(OnTargetHitEvent);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 处理目标被击中事件
|
||
/// </summary>
|
||
private void OnTargetHitEvent(TargetHitEvent eventData)
|
||
{
|
||
if (eventData.MissileId == Id)
|
||
{
|
||
Explode();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 导弹自毁
|
||
/// </summary>
|
||
public void SelfDestruct()
|
||
{
|
||
if (IsActive)
|
||
{
|
||
string reason = FlightTime >= MissileProperties.MaxFlightTime ? "超出最大飞行时间" :
|
||
FlightDistance >= MissileProperties.MaxFlightDistance ? "超出最大飞行距离" :
|
||
Position.Y <= 0 ? "高度小于等于0" :
|
||
!HasGuidance ? "失去引导" : "未知原因";
|
||
|
||
Console.WriteLine($"导弹 {Id} 自毁。原因: {reason}");
|
||
Deactivate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取导弹状态
|
||
/// </summary>
|
||
public override string GetStatus()
|
||
{
|
||
MissileRunningState missileRunningState = GetRunningState();
|
||
return $"导弹 {missileRunningState.Id}:\n" +
|
||
$" 位置: {missileRunningState.Position}\n" +
|
||
$" 速度: {missileRunningState.Speed:F2} m/s\n" +
|
||
$" 速度分量: {missileRunningState.Velocity}\n" +
|
||
$" 朝向: {missileRunningState.Orientation}\n" +
|
||
$" 飞行时间: {missileRunningState.FlightTime:F2}/{MissileProperties.MaxFlightTime:F2}\n" +
|
||
$" 飞行距离: {missileRunningState.FlightDistance:F2}/{MissileProperties.MaxFlightDistance:F2}\n" +
|
||
$" 发动机工作时间: {missileRunningState.EngineBurnTime:F2}/{MissileProperties.MaxEngineBurnTime:F2}\n" +
|
||
$" 有引导: {(missileRunningState.HasGuidance ? "是" : "否")}\n" +
|
||
$" 失去引导时间: {missileRunningState.LostGuidanceTime:F2}\n";
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新导弹的制导状态
|
||
/// </summary>
|
||
protected virtual void UpdateGuidanceStatus()
|
||
{
|
||
// 基类中的默认实现
|
||
}
|
||
|
||
public MissileRunningState GetRunningState()
|
||
{
|
||
return new MissileRunningState
|
||
{
|
||
Id = Id,
|
||
Type = MissileProperties.Type,
|
||
Position = Position,
|
||
Velocity = Velocity,
|
||
Orientation = Orientation,
|
||
Speed = Speed,
|
||
FlightTime = FlightTime,
|
||
FlightDistance = FlightDistance,
|
||
HasGuidance = HasGuidance,
|
||
LostGuidanceTime = LostGuidanceTime,
|
||
EngineBurnTime = EngineBurnTime,
|
||
IsActive = IsActive
|
||
};
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 表示导弹的运行状态信息
|
||
/// </summary>
|
||
public struct MissileRunningState
|
||
{
|
||
/// <summary>
|
||
/// 导弹ID
|
||
/// </summary>
|
||
public string Id { get; set; }
|
||
|
||
/// <summary>
|
||
/// 导弹类型
|
||
/// </summary>
|
||
public MissileType Type { get; set; }
|
||
|
||
/// <summary>
|
||
/// 当前位置
|
||
/// </summary>
|
||
public Vector3D Position { get; set; }
|
||
|
||
/// <summary>
|
||
/// 当前速度向量
|
||
/// </summary>
|
||
public Vector3D Velocity { get; set; }
|
||
|
||
/// <summary>
|
||
/// 当前朝向
|
||
/// </summary>
|
||
public Orientation Orientation { get; set; }
|
||
|
||
/// <summary>
|
||
/// 当前速度(米/秒)
|
||
/// </summary>
|
||
public double Speed { get; set; }
|
||
|
||
/// <summary>
|
||
/// 当前飞行时间(秒)
|
||
/// </summary>
|
||
public double FlightTime { get; set; }
|
||
|
||
/// <summary>
|
||
/// 当前飞行距离(米)
|
||
/// </summary>
|
||
public double FlightDistance { get; set; }
|
||
|
||
/// <summary>
|
||
/// 是否有制导
|
||
/// </summary>
|
||
public bool HasGuidance { get; set; }
|
||
|
||
/// <summary>
|
||
/// 失去制导时间(秒)
|
||
/// </summary>
|
||
public double LostGuidanceTime { get; set; }
|
||
|
||
/// <summary>
|
||
/// 当前发动机燃烧时间(秒)
|
||
/// </summary>
|
||
public double EngineBurnTime { get; set; }
|
||
|
||
/// <summary>
|
||
/// 是否处于活动状态
|
||
/// </summary>
|
||
public bool IsActive { get; set; }
|
||
}
|
||
}
|