286 lines
9.9 KiB
C#
286 lines
9.9 KiB
C#
using System;
|
||
using ActiveProtect.SimulationEnvironment;
|
||
|
||
namespace ActiveProtect.Models
|
||
{
|
||
public class TerminalSensitiveSubmunition : MissileBase
|
||
{
|
||
/// <summary>
|
||
/// 子弹阶段
|
||
/// </summary>
|
||
private enum SubmunitionStage
|
||
{
|
||
Separation,
|
||
Deceleration,
|
||
SpiralScan,
|
||
Attack,
|
||
Explode,
|
||
SelfDestruct
|
||
}
|
||
|
||
/// <summary>
|
||
/// 当前阶段
|
||
/// </summary>
|
||
private SubmunitionStage currentStage;
|
||
|
||
private const double SpiralRotationSpeed = 8 * Math.PI; // 4 rotations per second
|
||
private const double VerticalDescentSpeed = 10; // 10 m/s
|
||
private const double ScanAngle = 20 * Math.PI / 180; // 20 degrees in radians
|
||
|
||
// 减速高度 400米
|
||
private const double DecelerationHeight = 400;
|
||
|
||
// 扫描高度 200米
|
||
private const double ScanningHeight = 200;
|
||
|
||
// 自毁高度 20米
|
||
private const double SelfDestructHeight = 20;
|
||
|
||
// 攻击速度 500 m/s
|
||
private const double AttackSpeed = 500;
|
||
|
||
// 检测到目标的时间
|
||
private double? lastDetectionTime = null;
|
||
|
||
/// <summary>
|
||
/// 螺旋角度
|
||
/// </summary>
|
||
private double spiralAngle;
|
||
|
||
// 检测到目标的角度
|
||
private double detectionAngle;
|
||
|
||
// 弹载传感器
|
||
private readonly InfraredDetector infraredDetector;
|
||
private readonly MillimeterWaveRadiometer radiometer;
|
||
private readonly MillimeterWaveAltimeter altimeter;
|
||
private readonly LaserRangefinder rangefinder;
|
||
|
||
/// <summary>
|
||
/// 构造函数
|
||
/// </summary>
|
||
/// <param name="config">导弹配置</param>
|
||
/// <param name="manager">模拟管理器</param>
|
||
public TerminalSensitiveSubmunition(MissileConfig config, ISimulationManager manager)
|
||
: base(config, manager)
|
||
{
|
||
currentStage = SubmunitionStage.Separation;
|
||
spiralAngle = 0;
|
||
detectionAngle = 0;
|
||
|
||
// 初始化传感器
|
||
infraredDetector = new InfraredDetector(Position, Orientation, 100, 30);
|
||
radiometer = new MillimeterWaveRadiometer(Position, Orientation, 94e9, 1e-6);
|
||
altimeter = new MillimeterWaveAltimeter(this, 1000, 0.1); // 毫米波测高仪,测量精度0.1米
|
||
rangefinder = new LaserRangefinder(Position, Orientation, 1000, 1000);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新子弹的状态
|
||
/// </summary>
|
||
/// <param name="deltaTime">时间增量</param>
|
||
public override void Update(double deltaTime)
|
||
{
|
||
base.Update(deltaTime);
|
||
|
||
// 更新传感器
|
||
infraredDetector.Update(deltaTime);
|
||
radiometer.Update(deltaTime);
|
||
altimeter.Update(deltaTime);
|
||
rangefinder.Update(deltaTime);
|
||
|
||
switch (currentStage)
|
||
{
|
||
case SubmunitionStage.Separation:
|
||
UpdateSeparationStage(deltaTime);
|
||
break;
|
||
case SubmunitionStage.Deceleration:
|
||
UpdateDecelerationStage(deltaTime);
|
||
break;
|
||
case SubmunitionStage.SpiralScan:
|
||
UpdateSpiralScanStage(deltaTime);
|
||
break;
|
||
case SubmunitionStage.Attack:
|
||
UpdateAttackStage(deltaTime);
|
||
break;
|
||
case SubmunitionStage.Explode:
|
||
UpdateExplodeStage(deltaTime);
|
||
break;
|
||
case SubmunitionStage.SelfDestruct:
|
||
UpdateSelfDestructStage(deltaTime);
|
||
break;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 分离阶段
|
||
/// </summary>
|
||
private void UpdateSeparationStage(double deltaTime)
|
||
{
|
||
// 分离阶段
|
||
Vector3D deceleration = new(0, 9.8, 0);
|
||
Velocity += deceleration * deltaTime;
|
||
Position += Velocity * deltaTime;
|
||
|
||
if(!altimeter.IsActive)
|
||
{
|
||
// 激活毫米波测高雷达
|
||
altimeter.Activate();
|
||
}
|
||
|
||
// 检查高度是否小于等于减速高度
|
||
if(((AltimeterSensorData)altimeter.GetSensorData()).Altitude <= DecelerationHeight)
|
||
{
|
||
// 如果是,则进入减速阶段
|
||
currentStage = SubmunitionStage.Deceleration;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 减速阶段
|
||
/// </summary>
|
||
private void UpdateDecelerationStage(double deltaTime)
|
||
{
|
||
// 减速减旋,垂直速度减小
|
||
Vector3D deceleration = new Vector3D(0, 9.8, 0) - Velocity.Normalize() * 50; // 假设减速度为5m/s^2
|
||
Console.WriteLine($"降落伞打开,减速速度: {deceleration}");
|
||
Velocity += deceleration * deltaTime;
|
||
|
||
if (Velocity.Magnitude() <= VerticalDescentSpeed)
|
||
{
|
||
Velocity = new Vector3D(0, -VerticalDescentSpeed, 0);
|
||
}
|
||
|
||
if (((AltimeterSensorData)altimeter.GetSensorData()).Altitude <= ScanningHeight)
|
||
{
|
||
currentStage = SubmunitionStage.SpiralScan;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 扫描阶段
|
||
/// </summary>
|
||
private void UpdateSpiralScanStage(double deltaTime)
|
||
{
|
||
GuidanceAcceleration = Vector3D.Zero;
|
||
|
||
// 更新螺旋角度
|
||
spiralAngle = (spiralAngle + SpiralRotationSpeed * deltaTime) % (2 * Math.PI);
|
||
|
||
// 计算水平速度分量
|
||
double horizontalSpeed = VerticalDescentSpeed * Math.Tan(ScanAngle);
|
||
Vector3D horizontalVelocity = new(
|
||
Math.Cos(spiralAngle) * horizontalSpeed,
|
||
0,
|
||
Math.Sin(spiralAngle) * horizontalSpeed
|
||
);
|
||
|
||
// 更新速度
|
||
Velocity = new(horizontalVelocity.X, -VerticalDescentSpeed, horizontalVelocity.Z);
|
||
|
||
// 计算扫描方向
|
||
Vector3D scanDirection = new(
|
||
Math.Cos(spiralAngle) * Math.Sin(ScanAngle),
|
||
-Math.Cos(ScanAngle),
|
||
Math.Sin(spiralAngle) * Math.Sin(ScanAngle)
|
||
);
|
||
|
||
if (DetectTarget(scanDirection))
|
||
{
|
||
Console.WriteLine("检测到目标");
|
||
double currentTime = SimulationManager.CurrentTime;
|
||
if (lastDetectionTime == null)
|
||
{
|
||
lastDetectionTime = currentTime;
|
||
}
|
||
else
|
||
{
|
||
double timeSinceLastDetection = currentTime - lastDetectionTime.Value;
|
||
// 重新检测到目标的时间大于等于螺旋周期的90%,则二次确认目标
|
||
if (timeSinceLastDetection >= 0.9 * 2 * Math.PI / SpiralRotationSpeed)
|
||
{
|
||
Console.WriteLine($"目标确认,进入攻击阶段。距离上次检测时间:{timeSinceLastDetection:F2}秒");
|
||
currentStage = SubmunitionStage.Attack;
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 使用模式匹配简化类型转换
|
||
if (altimeter.GetSensorData() is AltimeterSensorData altimeterData &&
|
||
altimeterData.Altitude <= SelfDestructHeight)
|
||
{
|
||
currentStage = SubmunitionStage.SelfDestruct;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 攻击阶段
|
||
/// </summary>
|
||
private void UpdateAttackStage(double deltaTime)
|
||
{
|
||
Console.WriteLine("攻击阶段");
|
||
// 攻击逻辑
|
||
Vector3D targetPosition = SimulationManager.GetEntityById(TargetId).Position;
|
||
Vector3D direction = (targetPosition - Position).Normalize();
|
||
Velocity = direction * AttackSpeed;
|
||
Console.WriteLine($"导弹ID: {Id}, 距离目标: {DistanceToTarget}, 爆炸半径: {ExplosionRadius}");
|
||
if (DistanceToTarget <= ExplosionRadius)
|
||
{
|
||
currentStage = SubmunitionStage.Explode;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 爆炸阶段
|
||
/// </summary>
|
||
private void UpdateExplodeStage(double deltaTime)
|
||
{
|
||
Explode();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 自毁阶段
|
||
/// </summary>
|
||
private void UpdateSelfDestructStage(double deltaTime)
|
||
{
|
||
SelfDestruct();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 检测目标
|
||
/// </summary>
|
||
/// <param name="scanDirection">扫描方向</param>
|
||
/// <returns>是否检测到目标</returns>
|
||
private bool DetectTarget(Vector3D scanDirection)
|
||
{
|
||
Vector3D targetPosition = SimulationManager.GetEntityById(TargetId).Position;
|
||
Vector3D toTarget = (targetPosition - Position).Normalize();
|
||
|
||
// 检查目标是否在扫描线上
|
||
return Vector3D.DotProduct(scanDirection, toTarget) > Math.Cos(5 * Math.PI / 180); // 允许5度的误差
|
||
}
|
||
|
||
/// <summary>
|
||
/// 销毁子弹
|
||
/// </summary>
|
||
public override void Deactivate()
|
||
{
|
||
base.Deactivate();
|
||
infraredDetector.Deactivate();
|
||
radiometer.Deactivate();
|
||
altimeter.Deactivate();
|
||
rangefinder.Deactivate();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取子弹状态
|
||
/// </summary>
|
||
/// <returns>子弹状态</returns>
|
||
public override string GetStatus()
|
||
{
|
||
return $"{base.GetStatus()}\n运行状态: {currentStage}\n检测角度: {detectionAngle * 180 / Math.PI:F2}°\n螺旋角度: {spiralAngle * 180 / Math.PI:F2}°\n目标检测: {lastDetectionTime != null}";
|
||
}
|
||
}
|
||
}
|