322 lines
12 KiB
C#
322 lines
12 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using ActiveProtect.SimulationEnvironment;
|
||
|
||
namespace ActiveProtect.Models
|
||
{
|
||
public class TerminalSensitiveMissile : MissileBase
|
||
{
|
||
private enum TerminalSensitiveStage
|
||
{
|
||
Launch, // 发射阶段
|
||
Separation, // 分离阶段
|
||
Deceleration, // 减速阶段
|
||
SpiralScan, // 螺旋扫描阶段
|
||
Attack, // 攻击阶段
|
||
SelfDestruct // 自毁阶段
|
||
}
|
||
|
||
private TerminalSensitiveStage currentWorkingStage;
|
||
private Dictionary<TerminalSensitiveStage, Action<double>> stageStrategies;
|
||
|
||
private double spiralAngle;
|
||
private const double SpiralRotationSpeed = 4 * Math.PI; // 2 rotations per second
|
||
private const double VerticalDescentSpeed = 10; // 10 m/s
|
||
private const double ScanAngle = 30 * Math.PI / 180; // 30 degrees in radians
|
||
|
||
// 分离距离 1000米
|
||
private const double SeparationDistance = 1000;
|
||
|
||
// 分离高度 1000米
|
||
private const double SeparationHeight = 1000;
|
||
|
||
// 减速高度 400米
|
||
private const double DecelerationHeight = 400;
|
||
|
||
// 扫描高度 200米
|
||
private const double ScanningHeight = 200;
|
||
|
||
// 自毁高度 20米
|
||
private const double SelfDestructHeight = 20;
|
||
|
||
private Vector3D lastScanDirection;
|
||
private bool targetDetected;
|
||
private double detectionAngle;
|
||
|
||
//目标位置
|
||
private Vector3D TargetPosition;
|
||
|
||
//末敏弹子母弹分离位置
|
||
private Vector3D SeparationPosition;
|
||
|
||
public Vector3D GuidanceCommand { get; private set; }
|
||
|
||
public TerminalSensitiveMissile(string id, MissileConfig missileConfig, string targetId, ISimulationManager simulationManager)
|
||
: base(id, missileConfig, simulationManager)
|
||
{
|
||
spiralAngle = 0;
|
||
lastScanDirection = Vector3D.Zero;
|
||
targetDetected = false;
|
||
detectionAngle = 0;
|
||
GuidanceCommand = Vector3D.Zero;
|
||
|
||
TargetPosition = SimulationManager.GetEntityById(targetId).Position;
|
||
|
||
SeparationPosition = CalculatePointOnTrajectory(Position, TargetPosition, SeparationDistance, SeparationHeight);
|
||
|
||
// 初始化策略字典
|
||
stageStrategies = new Dictionary<TerminalSensitiveStage, Action<double>>
|
||
{
|
||
{ TerminalSensitiveStage.Launch, UpdateLaunchStage },
|
||
{ TerminalSensitiveStage.Separation, UpdateSeparationStage },
|
||
{ TerminalSensitiveStage.Deceleration, UpdateDecelerationStage },
|
||
{ TerminalSensitiveStage.SpiralScan, UpdateSpiralScanStage },
|
||
{ TerminalSensitiveStage.Attack, UpdateAttackStage },
|
||
{ TerminalSensitiveStage.SelfDestruct, UpdateSelfDestructStage }
|
||
};
|
||
|
||
currentWorkingStage = TerminalSensitiveStage.Launch;
|
||
}
|
||
|
||
public override void Update(double deltaTime)
|
||
{
|
||
//base.Update(deltaTime);
|
||
if (!IsActive) return;
|
||
|
||
if (ShouldSelfDestruct())
|
||
{
|
||
SelfDestruct();
|
||
return;
|
||
}
|
||
|
||
Console.WriteLine($"末敏弹 {Id} 当前位置: {Position}");
|
||
Console.WriteLine($"末敏弹 {Id} 分离位置: {SeparationPosition}");
|
||
|
||
// 使用当前阶段的策略更新导弹状态
|
||
if (stageStrategies.TryGetValue(currentWorkingStage, out var updateStrategy))
|
||
{
|
||
updateStrategy(deltaTime);
|
||
}
|
||
|
||
}
|
||
|
||
private void UpdateLaunchStage(double deltaTime)
|
||
{
|
||
// 无动力抛物线飞行
|
||
ApplyGravity(deltaTime);
|
||
|
||
base.UpdateMotionState(deltaTime, GuidanceCommand);
|
||
|
||
if (Vector3D.Distance(Position, SeparationPosition) <= 200)
|
||
{
|
||
currentWorkingStage = TerminalSensitiveStage.Separation;
|
||
}
|
||
}
|
||
|
||
private void UpdateSeparationStage(double deltaTime)
|
||
{
|
||
// 子母弹分离逻辑
|
||
// 这里可以添加分离的具体实现,比如创建子弹等
|
||
Console.WriteLine($"末敏弹 {Id} 进入分离");
|
||
|
||
switch(Velocity.Magnitude())
|
||
{
|
||
case >= 200:
|
||
GuidanceCommand = new Vector3D(400, -400, 0);
|
||
break;
|
||
case >= 100:
|
||
GuidanceCommand = new Vector3D(30, -30, 0);
|
||
break;
|
||
case >= 50:
|
||
GuidanceCommand = new Vector3D(20, -20, 0);
|
||
break;
|
||
case >= 20:
|
||
GuidanceCommand = new Vector3D(5, -10, 0);
|
||
break;
|
||
default:
|
||
GuidanceCommand = new Vector3D(0, -10, 0);
|
||
break;
|
||
}
|
||
base.UpdateMotionState(deltaTime, GuidanceCommand);
|
||
|
||
if (Position.Y <= DecelerationHeight)
|
||
{
|
||
currentWorkingStage = TerminalSensitiveStage.Deceleration;
|
||
}
|
||
}
|
||
|
||
private void UpdateDecelerationStage(double deltaTime)
|
||
{
|
||
Console.WriteLine($"末敏弹 {Id} 进入减速");
|
||
// 减速下降
|
||
Velocity = new Vector3D(0, -VerticalDescentSpeed, 0);
|
||
Position += Velocity * deltaTime;
|
||
|
||
if (Position.Y <= ScanningHeight)
|
||
{
|
||
currentWorkingStage = TerminalSensitiveStage.SpiralScan;
|
||
}
|
||
}
|
||
|
||
private void UpdateSpiralScanStage(double deltaTime)
|
||
{
|
||
Console.WriteLine($"末敏弹 {Id} 进入螺旋扫描");
|
||
|
||
spiralAngle += SpiralRotationSpeed * deltaTime;
|
||
|
||
// 计算水平速度分量
|
||
double horizontalSpeed = VerticalDescentSpeed * Math.Tan(ScanAngle);
|
||
Vector3D horizontalVelocity = new Vector3D(
|
||
Math.Cos(spiralAngle) * horizontalSpeed,
|
||
0,
|
||
Math.Sin(spiralAngle) * horizontalSpeed
|
||
);
|
||
|
||
// 更新速度
|
||
Velocity = new Vector3D(horizontalVelocity.X, -VerticalDescentSpeed, horizontalVelocity.Z);
|
||
|
||
// 计算扫描方向
|
||
Vector3D scanDirection = new Vector3D(
|
||
Math.Cos(spiralAngle) * Math.Sin(ScanAngle),
|
||
-Math.Cos(ScanAngle),
|
||
Math.Sin(spiralAngle) * Math.Sin(ScanAngle)
|
||
);
|
||
|
||
if (DetectTarget(scanDirection))
|
||
{
|
||
if (!targetDetected)
|
||
{
|
||
targetDetected = true;
|
||
detectionAngle = spiralAngle;
|
||
}
|
||
else if (Math.Abs(spiralAngle - detectionAngle) < 0.1) // 允许一定的误差
|
||
{
|
||
currentWorkingStage = TerminalSensitiveStage.Attack;
|
||
}
|
||
}
|
||
|
||
lastScanDirection = scanDirection;
|
||
|
||
if (Position.Y <= SelfDestructHeight)
|
||
{
|
||
currentWorkingStage = TerminalSensitiveStage.SelfDestruct;
|
||
}
|
||
}
|
||
|
||
private void UpdateAttackStage(double deltaTime)
|
||
{
|
||
// 攻击逻辑
|
||
Vector3D targetPosition = SimulationManager.GetEntityById(TargetId).Position;
|
||
Vector3D direction = (targetPosition - Position).Normalize();
|
||
Velocity = direction * MaxSpeed;
|
||
|
||
if (Vector3D.Distance(Position, targetPosition) < 1)
|
||
{
|
||
Explode();
|
||
}
|
||
}
|
||
|
||
private void UpdateSelfDestructStage(double deltaTime)
|
||
{
|
||
// 实现自毁逻辑
|
||
Explode();
|
||
}
|
||
|
||
private bool DetectTarget(Vector3D scanDirection)
|
||
{
|
||
Vector3D targetPosition = SimulationManager.GetEntityById(TargetId).Position;
|
||
Vector3D toTarget = (targetPosition - Position).Normalize();
|
||
|
||
// 检查目标是否在扫描线上
|
||
return Vector3D.DotProduct(scanDirection, toTarget) > Math.Cos(0.5 * Math.PI / 180); // 允许0.5度的误差
|
||
}
|
||
|
||
private void ApplyGravity(double deltaTime)
|
||
{
|
||
GuidanceCommand = new Vector3D(0, -9.81, 0);
|
||
}
|
||
|
||
public override string GetStatus()
|
||
{
|
||
string baseStatus = base.GetStatus().Replace("导弹", "末敏弹");
|
||
string additionalStatus = $"\n 扫描阶段: {(currentWorkingStage == TerminalSensitiveStage.SpiralScan ? "有效" : "无效")} \n";
|
||
return baseStatus + additionalStatus;
|
||
}
|
||
|
||
public override void Activate()
|
||
{
|
||
base.Activate();
|
||
// SimulationManager.SubscribeToEvent<LaserBeamStartEvent>(OnLaserBeamStart);
|
||
// SimulationManager.SubscribeToEvent<LaserBeamStopEvent>(OnLaserBeamStop);
|
||
// SimulationManager.SubscribeToEvent<LaserBeamUpdateEvent>(OnLaserBeamUpdate);
|
||
}
|
||
|
||
public override void Deactivate()
|
||
{
|
||
base.Deactivate();
|
||
// SimulationManager.UnsubscribeFromEvent<LaserBeamStartEvent>(OnLaserBeamStart);
|
||
// SimulationManager.UnsubscribeFromEvent<LaserBeamStopEvent>(OnLaserBeamStop);
|
||
// SimulationManager.UnsubscribeFromEvent<LaserBeamUpdateEvent>(OnLaserBeamUpdate);
|
||
}
|
||
|
||
public static (double angle, double distance) CalculateLaunchParameters(double initialVelocity, double targetHeight, double targetDistance)
|
||
{
|
||
double g = 9.8; // 重力加速度
|
||
double v = initialVelocity;
|
||
double y = targetHeight;
|
||
double x = targetDistance;
|
||
|
||
// 计算发射角度(弧度)
|
||
double angle = Math.Atan((v * v + Math.Sqrt(Math.Pow(v, 4) - g * (g * x * x + 2 * y * v * v))) / (g * x));
|
||
|
||
// 计算水平飞行距离
|
||
double t = x / (v * Math.Cos(angle));
|
||
double totalDistance = v * Math.Cos(angle) * t;
|
||
|
||
return (angle, totalDistance);
|
||
}
|
||
|
||
public static Vector3D CalculateLaunchPosition(Vector3D knownPoint, Vector3D velocity)
|
||
{
|
||
double g = 9.8; // 重力加速度
|
||
double x = knownPoint.X;
|
||
double y = knownPoint.Y;
|
||
double vx = velocity.X;
|
||
double vy = velocity.Y;
|
||
|
||
// 计算时间 t
|
||
double t = (-vy - Math.Sqrt(vy * vy + 2 * g * y)) / -g;
|
||
|
||
// 计算发射点的 x 坐标
|
||
double launchX = x - vx * t;
|
||
|
||
// 发射点的 y 和 z 坐标为 0
|
||
return new Vector3D(launchX, 0, 0);
|
||
}
|
||
|
||
public static Vector3D CalculatePointOnTrajectory(Vector3D launchPosition, Vector3D targetPosition, double distanceFromTarget, double height)
|
||
{
|
||
// 确保发射位置和目标位置的y坐标为0
|
||
launchPosition = new Vector3D(launchPosition.X, 0, launchPosition.Z);
|
||
targetPosition = new Vector3D(targetPosition.X, 0, targetPosition.Z);
|
||
|
||
// 计算发射方向向量
|
||
Vector3D direction = targetPosition - launchPosition;
|
||
|
||
// 计算总距离
|
||
double totalDistance = direction.Magnitude();
|
||
|
||
// 归一化方向向量
|
||
direction = direction.Normalize();
|
||
|
||
// 计算所需点的位置
|
||
Vector3D pointOnTrajectory = targetPosition - direction * distanceFromTarget;
|
||
|
||
// 返回结果,y坐标设置为指定的高度
|
||
return new Vector3D(pointOnTrajectory.X, height, pointOnTrajectory.Z);
|
||
}
|
||
|
||
|
||
}
|
||
}
|