ActiveProtect/Models/TerminalSensitiveMissile.cs

322 lines
12 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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