修改了导弹加速阶段、目标指示器的终止逻辑

This commit is contained in:
Tian jianyong 2024-10-09 22:19:02 +08:00
parent f36f00572c
commit db529f1bd1
14 changed files with 576 additions and 328 deletions

View File

@ -1,52 +1,69 @@
您是 C#、Unity 和可扩展游戏开发的专家。
# C 开发规则
关键原则 您是一名C#开发专家。
- 编写清晰、技术性的响应,提供精确的 C# 和 Unity 示例。
- 尽可能使用 Unity 的内置功能和工具,以充分利用其能力。
- 优先考虑可读性和可维护性;遵循 C# 编码规范和 Unity 最佳实践。
- 使用描述性的变量和函数名称;遵循命名约定(例如,公共成员使用 PascalCase私有成员使用 camelCase
- 以模块化的方式构建项目,使用 Unity 的基于组件的架构,以促进可重用性和关注点分离。
C#/Unity ## 代码风格和结构
- 对于附加到 GameObject 的脚本组件,使用 MonoBehaviour对于数据容器和共享资源优先使用 ScriptableObjects。 - 编写简洁、符合习惯的 C# 代码,并提供准确的示例。
- 利用 Unity 的物理引擎和碰撞检测系统来实现游戏机制和交互。 - 根据需要使用面向对象和函数式编程模式。
- 使用 Unity 的输入系统处理跨多个平台的玩家输入。 - 优先使用 LINQ 和 lambda 表达式进行集合操作。
- 利用 Unity 的 UI 系统Canvas、UI 元素)创建用户界面。 - 使用描述性变量和方法名称(例如,'IsUserSignedIn', 'CalculateTotal')。
- 严格遵循组件模式,以实现关注点的清晰分离和模块化。
- 在 Unity 的单线程环境中,使用协程处理基于时间的操作和异步任务。
错误处理和调试 ## 命名约定
- 在适当的地方使用 try-catch 块实现错误处理,特别是对于文件 I/O 和网络操作。 - 类名、方法名和公共成员使用 PascalCase。
- 使用 Unity 的 Debug 类进行日志记录和调试例如Debug.Log、Debug.LogWarning、Debug.LogError - 局部变量和私有字段使用 camelCase。
- 利用 Unity 的分析器和帧调试器识别和解决性能问题。 - 常量使用 UPPERCASE。
- 实现自定义错误消息和调试可视化,以改善开发体验。 - 接口名称以 "I" 开头(例如,'IUserService')。
- 使用 Unity 的断言系统Debug.Assert在开发过程中捕获逻辑错误。
依赖项 ## C# 使用
- Unity 引擎 - 在适当的情况下使用 C# 10+ 特性(例如,记录类型、模式匹配、空合并赋值)。
- .NET 框架(与您的 Unity 版本兼容的版本) - 有效使用 Entity Framework Core 进行数据库操作。
- Unity 资产商店包(根据特定功能需要) - 使用依赖注入实现松耦合和可测试性。
- 第三方插件(经过仔细审查以确保兼容性和性能) - 类的构造函数使用主构造函数,成员变量使用属性初始化。
Unity 特定指南 ## 语法和格式
- 使用预制件Prefabs创建可重用的游戏对象和 UI 元素。 - 遵循 C# 编码约定https://docs.microsoft.com/en-us/dotnet/csharp/fundamentals/coding-style/coding-conventions
- 将游戏逻辑保留在脚本中;使用 Unity 编辑器进行场景组合和初始设置。 - 使用 C# 的表达式语法(例如,空条件运算符、字符串插值)
- 利用 Unity 的动画系统Animator、动画剪辑进行角色和对象动画。 - 当类型明显时,使用 'var' 进行隐式类型声明。
- 应用 Unity 的内置光照和后处理效果以增强视觉效果。
- 使用 Unity 的内置测试框架进行单元测试和集成测试。
- 利用 Unity 的资源包系统进行高效的资源管理和加载。
- 使用 Unity 的标签和层系统进行对象分类和碰撞过滤。
性能优化 ## 错误处理和验证
- 对于频繁实例化和销毁的对象,使用对象池 - 对于异常情况使用异常,而不是控制流。
- 通过批处理材质和使用精灵和 UI 元素的图集来优化绘制调用 - 使用内置的 .NET 日志记录或第三方日志记录器实现适当的错误日志记录。
- 实现细节层次LOD系统以提高复杂 3D 模型的渲染性能 - 使用数据注解或 Fluent Validation 进行模型验证
- 使用 Unity 的作业系统和 Burst 编译器进行 CPU 密集型操作 - 实现全局异常处理的中间件
- 通过使用简化的碰撞网格和调整固定时间步长来优化物理性能 - 返回适当的 HTTP 状态码和一致的错误响应
关键约定 ## API 设计
1. 遵循 Unity 的基于组件的架构,以实现模块化和可重用的游戏元素。 - 遵循 RESTful API 设计原则。
2. 在开发的每个阶段优先考虑性能优化和内存管理。 - 在控制器中使用属性路由。
3. 维护清晰和逻辑的项目结构,以增强可读性和资产管理。 - 为您的 API 实现版本控制。
- 使用操作过滤器处理跨切关注点。
请参考 Unity 文档和 C# 编程指南,以获取脚本、游戏架构和性能优化的最佳实践。 ## 性能优化
- 对于 I/O 密集型操作,使用 async/await 进行异步编程。
- 使用 IMemoryCache 或分布式缓存实现缓存策略。
- 使用高效的 LINQ 查询,避免 N+1 查询问题。
- 对于大型数据集实现分页。
## 关键约定
- 使用依赖注入实现松耦合和可测试性。
- 根据复杂性实现仓储模式或直接使用 Entity Framework Core。
- 如有需要,使用 AutoMapper 进行对象到对象的映射。
- 使用 IHostedService 或 BackgroundService 实现后台任务。
## 测试
- 使用 xUnit、NUnit 或 MSTest 编写单元测试。
- 使用 Moq 或 NSubstitute 模拟依赖项。
- 为 API 端点实现集成测试。
## 安全性
- 使用身份验证和授权中间件。
- 实现 JWT 身份验证以进行无状态 API 身份验证。
- 使用 HTTPS 并强制 SSL。
- 实现适当的 CORS 策略。
## API 文档
- 使用 Swagger/OpenAPI 进行 API 文档(根据安装的 Swashbuckle.AspNetCore 包)。
- 为控制器和模型提供 XML 注释,以增强 Swagger 文档。
遵循官方 Microsoft 文档,以获取路由、控制器、模型和其他 API 组件的最佳实践。

View File

@ -15,6 +15,10 @@ Global
{7F47A2C7-1087-440B-82F7-A1BF50D30A1B}.Debug|Any CPU.Build.0 = Debug|Any CPU {7F47A2C7-1087-440B-82F7-A1BF50D30A1B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7F47A2C7-1087-440B-82F7-A1BF50D30A1B}.Release|Any CPU.ActiveCfg = Release|Any CPU {7F47A2C7-1087-440B-82F7-A1BF50D30A1B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7F47A2C7-1087-440B-82F7-A1BF50D30A1B}.Release|Any CPU.Build.0 = Release|Any CPU {7F47A2C7-1087-440B-82F7-A1BF50D30A1B}.Release|Any CPU.Build.0 = Release|Any CPU
{644AFA6F-7DEE-4438-85C3-1D380B052E3D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{644AFA6F-7DEE-4438-85C3-1D380B052E3D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{644AFA6F-7DEE-4438-85C3-1D380B052E3D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{644AFA6F-7DEE-4438-85C3-1D380B052E3D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View File

@ -138,14 +138,6 @@ namespace ActiveProtect.Models
} }
} }
public enum MissileType
{
StandardMissile, // 标准导弹
SemiActiveLaserGuidance, // 半主动激光制导
LaserBeamRiderGuidance, // 激光束制导
InfraredCommandGuidance, // 红外指令制导
ImagingInfraredTerminalGuidance, // 成像红外终端制导
MillimeterWaveTerminalGuidance // 毫米波终端制导
}
} }

View File

@ -6,7 +6,6 @@ namespace ActiveProtect.Models
{ {
bool IsIlluminated { get; } bool IsIlluminated { get; }
void Illuminate(); void Illuminate();
// 移除重复的 Illuminate 方法(如果存在)
void StopIllumination(); void StopIllumination();
Vector3D Position { get; } Vector3D Position { get; }
} }

View File

@ -6,18 +6,21 @@ namespace ActiveProtect.Models
public class LaserDesignator : SimulationElement public class LaserDesignator : SimulationElement
{ {
public string TargetId { get; private set; } public string TargetId { get; private set; }
public string MissileId { get; private set; }
public double JammingThreshold { get; private set; } = 0.0; // 调整干扰阈值 public double JammingThreshold { get; private set; } = 0.0; // 调整干扰阈值
public bool IsJammed { get; private set; } = false; public bool IsJammed { get; private set; } = false;
public double MaxIlluminationRange { get; private set; } public double MaxIlluminationRange { get; private set; }
private bool IsIlluminating { get; set; } = false; private bool IsIlluminating { get; set; } = false;
public LaserDesignator(string id, string targetId, LaserDesignatorConfig config, ISimulationManager simulationManager) public LaserDesignator(string id, string targetId, string missileId, LaserDesignatorConfig config, ISimulationManager simulationManager)
: base(id, config.InitialPosition, new Orientation(), simulationManager) : base(id, config.InitialPosition, new Orientation(), simulationManager)
{ {
TargetId = targetId; TargetId = targetId;
MissileId = missileId;
IsActive = true; IsActive = true;
MaxIlluminationRange = config.MaxIlluminationRange; MaxIlluminationRange = config.MaxIlluminationRange;
SimulationManager.SubscribeToEvent<LaserJammingEvent>(OnLaserJamming); SimulationManager.SubscribeToEvent<LaserJammingEvent>(OnLaserJamming);
SimulationManager.SubscribeToEvent<EntityDeactivatedEvent>(OnEntityDeactivatedEvent);
} }
public override void Update(double deltaTime) public override void Update(double deltaTime)
@ -150,6 +153,15 @@ namespace ActiveProtect.Models
}); });
} }
private void OnEntityDeactivatedEvent(EntityDeactivatedEvent evt)
{
if (evt.DeactivatedEntityId == TargetId || evt.DeactivatedEntityId == MissileId)
{
DeactivateLaser();
Deactivate();
}
}
public override string GetStatus() public override string GetStatus()
{ {
return $"激光目标指示器 {Id}:\n" + return $"激光目标指示器 {Id}:\n" +

View File

@ -24,16 +24,15 @@ namespace ActiveProtect.Models
maxJammingPower = config.MaxJammingPower; maxJammingPower = config.MaxJammingPower;
initialJammingPower = config.InitialJammingPower; initialJammingPower = config.InitialJammingPower;
powerIncreaseRate = config.PowerIncreaseRate; powerIncreaseRate = config.PowerIncreaseRate;
SimulationManager.SubscribeToEvent<LaserIlluminationEvent>(OnLaserIllumination); SimulationManager.SubscribeToEvent<LaserWarnerAlarmEvent>(OnLaserWarnerAlarmEvent);
SimulationManager.SubscribeToEvent<LaserIlluminationStopEvent>(OnLaserIlluminationStop); SimulationManager.SubscribeToEvent<LaserWarnerAlarmStopEvent>(OnLaserWarnerAlarmStopEvent);
} }
public override void Update(double deltaTime) public override void Update(double deltaTime)
{ {
if (!IsActive) return; if (!IsActive) return;
var tank = SimulationManager.GetEntityById(MonitoredEntityId) as Tank; if (SimulationManager.GetEntityById(MonitoredEntityId) is Tank tank)
if (tank != null)
{ {
Position = tank.Position; Position = tank.Position;
Orientation = tank.Orientation; Orientation = tank.Orientation;
@ -62,7 +61,7 @@ namespace ActiveProtect.Models
} }
} }
private void OnLaserIllumination(LaserIlluminationEvent evt) private void OnLaserWarnerAlarmEvent(LaserWarnerAlarmEvent evt)
{ {
if (evt.TargetId == MonitoredEntityId) if (evt.TargetId == MonitoredEntityId)
{ {
@ -70,7 +69,7 @@ namespace ActiveProtect.Models
} }
} }
private void OnLaserIlluminationStop(LaserIlluminationStopEvent evt) private void OnLaserWarnerAlarmStopEvent(LaserWarnerAlarmStopEvent evt)
{ {
if (evt.TargetId == MonitoredEntityId) if (evt.TargetId == MonitoredEntityId)
{ {
@ -112,8 +111,8 @@ namespace ActiveProtect.Models
protected override void Deactivate() protected override void Deactivate()
{ {
base.Deactivate(); base.Deactivate();
SimulationManager.UnsubscribeFromEvent<LaserIlluminationEvent>(OnLaserIllumination); SimulationManager.UnsubscribeFromEvent<LaserWarnerAlarmEvent>(OnLaserWarnerAlarmEvent);
SimulationManager.UnsubscribeFromEvent<LaserIlluminationStopEvent>(OnLaserIlluminationStop); SimulationManager.UnsubscribeFromEvent<LaserWarnerAlarmStopEvent>(OnLaserWarnerAlarmStopEvent);
} }
} }
} }

View File

@ -5,7 +5,7 @@ namespace ActiveProtect.Models
{ {
public class LaserSemiActiveGuidedMissile : Missile public class LaserSemiActiveGuidedMissile : Missile
{ {
private const double LaserLockDistance = 2000; // 1公里,单位:米 private const double LaserLockDistance = 1500; // 锁定距离,单位:米
public LaserSemiActiveGuidedMissile( public LaserSemiActiveGuidedMissile(
string id, string id,
@ -13,19 +13,15 @@ namespace ActiveProtect.Models
ISimulationManager simulationManager) ISimulationManager simulationManager)
: base(id, missileConfig, simulationManager) : base(id, missileConfig, simulationManager)
{ {
Type = MissileType.SemiActiveLaserGuidance; Type = MissileType.LaserSemiActiveGuidance;
simulationManager.SubscribeToEvent<LaserIlluminationEvent>(OnLaserIllumination); simulationManager.SubscribeToEvent<LaserIlluminationEvent>(OnLaserIllumination);
simulationManager.SubscribeToEvent<LaserIlluminationStopEvent>(OnLaserIlluminationStop); simulationManager.SubscribeToEvent<LaserIlluminationStopEvent>(OnLaserIlluminationStop);
} }
public override void Update(double deltaTime) protected override void UpdateGuidanceStatus()
{ {
base.Update(deltaTime); bool previousHasGuidance = HasGuidance;
UpdateGuidanceStatus();
}
private void UpdateGuidanceStatus()
{
if (SimulationManager.GetEntityById(TargetId) is ILaserIlluminatable target) if (SimulationManager.GetEntityById(TargetId) is ILaserIlluminatable target)
{ {
bool isIlluminated = target.IsIlluminated; bool isIlluminated = target.IsIlluminated;
@ -37,12 +33,24 @@ namespace ActiveProtect.Models
Console.WriteLine($" 距离目标: {DistanceToTarget:F2} m (最大锁定距离: {LaserLockDistance} m)"); Console.WriteLine($" 距离目标: {DistanceToTarget:F2} m (最大锁定距离: {LaserLockDistance} m)");
Console.WriteLine($" 是否在锁定范围内: {isWithinRange}"); Console.WriteLine($" 是否在锁定范围内: {isWithinRange}");
Console.WriteLine($" 引导状态: {(HasGuidance ? "" : "")}"); Console.WriteLine($" 引导状态: {(HasGuidance ? "" : "")}");
if (!HasGuidance && previousHasGuidance)
{
Console.WriteLine($"激光半主动制导导弹 {Id} 失去引导");
LastKnownVelocity = Velocity;
}
else if (HasGuidance && !previousHasGuidance)
{
Console.WriteLine($"激光半主动制导导弹 {Id} 获得引导");
}
} }
else else
{ {
HasGuidance = false; HasGuidance = false;
Console.WriteLine($"激光半主动制导导弹 {Id} 无法找到目标 {TargetId}"); Console.WriteLine($"激光半主动制导导弹 {Id} 无法找到目标 {TargetId}");
} }
base.UpdateGuidanceStatus();
} }
private void OnLaserIllumination(LaserIlluminationEvent evt) private void OnLaserIllumination(LaserIlluminationEvent evt)

View File

@ -63,6 +63,7 @@ namespace ActiveProtect.Models
{ {
IsAlarming = true; IsAlarming = true;
alarmTimer = 0; alarmTimer = 0;
PublishEvent(new LaserWarnerAlarmEvent() { TargetId = MonitoredEntityId });
Console.WriteLine($"激光告警器 {Id} 发出警报!"); Console.WriteLine($"激光告警器 {Id} 发出警报!");
} }
} }
@ -73,6 +74,7 @@ namespace ActiveProtect.Models
{ {
IsAlarming = false; IsAlarming = false;
alarmTimer = 0; alarmTimer = 0;
PublishEvent(new LaserWarnerAlarmStopEvent() { TargetId = MonitoredEntityId });
Console.WriteLine($"激光告警器 {Id} 停止警报"); Console.WriteLine($"激光告警器 {Id} 停止警报");
} }
} }

View File

@ -11,23 +11,7 @@ namespace ActiveProtect.Models
/// <summary> /// <summary>
/// 导弹类型 /// 导弹类型
/// </summary> /// </summary>
public MissileType Type { get; protected set; } public MissileType Type { get; protected set; }
/// <summary>
/// 导弹飞行的各个阶段
/// </summary>
public enum FlightStage
{
Launch, // 发射阶段
Acceleration, // 加速阶段
Cruise, // 巡航阶段
TerminalGuidance, // 终端制导阶段
Attack, // 攻击阶段
Explosion // 爆炸阶段
}
public double Speed { get; protected set; } public double Speed { get; protected set; }
public double MaxSpeed { get; protected set; } public double MaxSpeed { get; protected set; }
public string TargetId { get; protected set; } public string TargetId { get; protected set; }
@ -38,8 +22,7 @@ namespace ActiveProtect.Models
public double DistanceToTarget { get; protected set; } public double DistanceToTarget { get; protected set; }
public MissileDistanceParams DistanceParams { get; protected set; } public MissileDistanceParams DistanceParams { get; protected set; }
public FlightStageConfig StageConfig { get; protected set; } public FlightStageConfig StageConfig { get; protected set; }
public FlightStage CurrentStage { get; protected set; } public FlightStage CurrentStage { get; protected set; }
protected Vector3D Velocity; protected Vector3D Velocity;
private Vector3D LastTargetPosition; private Vector3D LastTargetPosition;
private const double N = 3; // 比例导引系数 private const double N = 3; // 比例导引系数
@ -52,9 +35,17 @@ namespace ActiveProtect.Models
public double ProportionalNavigationCoefficient { get; set; } public double ProportionalNavigationCoefficient { get; set; }
public bool HasGuidance { get; protected set; } = true; public bool HasGuidance { get; protected set; } = false;
protected double LostGuidanceTime { get; set; } = 0; protected double LostGuidanceTime { get; set; } = 0;
protected const double MaxLostGuidanceTime = 1.0; // 1秒后自毁 protected Vector3D LastKnownVelocity = Vector3D.Zero;
public const double LAUNCH_SPEED = 10; // 发射速度单位m/s
public const double LAUNCH_DURATION = 0.5; // 发射阶持续时间,单位:秒
private IMissileStageStrategy currentStage;
private Dictionary<FlightStage, IMissileStageStrategy> stageStrategies;
// 添加质量属性
public double Mass { get; protected set; } = 100; // 默认质量为100kg可以根据需要调整
public Missile(string id, MissileConfig missileConfig, ISimulationManager simulationManager) public Missile(string id, MissileConfig missileConfig, ISimulationManager simulationManager)
: base(id, missileConfig.InitialPosition, missileConfig.InitialOrientation, simulationManager) : base(id, missileConfig.InitialPosition, missileConfig.InitialOrientation, simulationManager)
@ -78,34 +69,191 @@ namespace ActiveProtect.Models
Vector3D horizontalDirection = new Vector3D(Orientation.ToVector().X, 0, Orientation.ToVector().Z).Normalize(); Vector3D horizontalDirection = new Vector3D(Orientation.ToVector().X, 0, Orientation.ToVector().Z).Normalize();
Velocity = horizontalDirection * missileConfig.InitialSpeed; Velocity = horizontalDirection * missileConfig.InitialSpeed;
// 设置初始阶段 // 初始化策略字典
CurrentStage = StageConfig.EnableLaunch ? FlightStage.Launch : stageStrategies = new Dictionary<FlightStage, IMissileStageStrategy>
StageConfig.EnableAcceleration ? FlightStage.Acceleration : {
StageConfig.EnableCruise ? FlightStage.Cruise : { FlightStage.Launch, new LaunchStageStrategy(this) },
StageConfig.EnableTerminalGuidance ? FlightStage.TerminalGuidance : { FlightStage.Acceleration, new AccelerationStageStrategy(this) },
StageConfig.EnableAttack ? FlightStage.Attack : FlightStage.Cruise; { FlightStage.Cruise, new CruiseStageStrategy(this) },
{ FlightStage.TerminalGuidance, new TerminalGuidanceStageStrategy(this) },
{ FlightStage.Attack, new AttackStageStrategy(this) }
};
Console.WriteLine($"导弹 {Id} 的初始阶: {CurrentStage}"); // 设置初始阶段
SetInitialStage();
currentStage = stageStrategies[CurrentStage];
LastTargetPosition = Position; // 初始化 LastTargetPosition LastTargetPosition = Position; // 初始化 LastTargetPosition
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) public override void Update(double deltaTime)
{ {
if (!IsActive) return; if (!IsActive) return;
// 首先检查是否应该自毁
if (ShouldSelfDestruct()) if (ShouldSelfDestruct())
{ {
SelfDestruct(); SelfDestruct();
return; return;
} }
// 更新发动机燃烧时间
UpdateEngineBurnTime(deltaTime); UpdateEngineBurnTime(deltaTime);
(Position, Velocity) = UpdatePositionAndVelocityRK4(deltaTime);
// 使用 RK4 方法更新导弹状态 Speed = Velocity.Magnitude();
Orientation = Orientation.FromVector(Velocity);
FlightTime += deltaTime;
FlightDistance += Speed * deltaTime;
DistanceToTarget = Vector3D.Distance(Position, SimulationManager.GetEntityById(TargetId).Position);
if (CheckHit())
{
Explode();
return;
}
UpdateGuidanceStatus();
currentStage.Update(deltaTime);
}
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(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 k1, k2, k3, k4;
Vector3D v1, v2, v3, v4; Vector3D v1, v2, v3, v4;
@ -114,53 +262,25 @@ namespace ActiveProtect.Models
(k3, v3) = CalculateDerivatives(Position + k2 * (deltaTime / 2), Velocity + v2 * (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); (k4, v4) = CalculateDerivatives(Position + k3 * deltaTime, Velocity + v3 * deltaTime, deltaTime);
Position += (k1 + k2 * 2 + k3 * 2 + k4) * (deltaTime / 6); Vector3D newPosition = Position + (k1 + k2 * 2 + k3 * 2 + k4) * (deltaTime / 6);
Velocity += (v1 + v2 * 2 + v3 * 2 + v4) * (deltaTime / 6); Vector3D newVelocity = Velocity + (v1 + v2 * 2 + v3 * 2 + v4) * (deltaTime / 6);
// 更新其他状态 // 限制速度不超过最大速度
Speed = Velocity.Magnitude(); if (newVelocity.Magnitude() > MaxSpeed)
if (Speed > MaxSpeed)
{ {
Speed = MaxSpeed; newVelocity = newVelocity.Normalize() * MaxSpeed;
Velocity = Velocity.Normalize() * MaxSpeed;
} }
Orientation = Orientation.FromVector(Velocity); return (newPosition, newVelocity);
FlightTime += deltaTime;
FlightDistance += Speed * deltaTime;
DistanceToTarget = Vector3D.Distance(Position, SimulationManager.GetEntityById(TargetId).Position);
// 检查是否命中目标
if (CheckHit())
{
Explode();
return;
}
// 更新飞行阶段
UpdateFlightStage();
if (!HasGuidance)
{
HandleLostGuidance(deltaTime);
}
else
{
LostGuidanceTime = 0;
}
// 发布事件示例
if (CurrentStage == FlightStage.Launch)
{
PublishEvent(new MissileFireEvent { TargetId = TargetId });
}
} }
// 检查是否命中目标
private bool CheckHit() private bool CheckHit()
{ {
return DistanceToTarget <= DistanceParams.ExplosionDistance; return DistanceToTarget <= DistanceParams.ExplosionDistance;
} }
// 检查是否应该自毁
private bool ShouldSelfDestruct() private bool ShouldSelfDestruct()
{ {
if (FlightTime >= MaxFlightTime) if (FlightTime >= MaxFlightTime)
@ -181,6 +301,7 @@ namespace ActiveProtect.Models
return false; return false;
} }
// 更新发动机燃烧时间
private void UpdateEngineBurnTime(double deltaTime) private void UpdateEngineBurnTime(double deltaTime)
{ {
if (CurrentStage == FlightStage.Acceleration && EngineBurnTime < MaxEngineBurnTime) if (CurrentStage == FlightStage.Acceleration && EngineBurnTime < MaxEngineBurnTime)
@ -189,74 +310,20 @@ namespace ActiveProtect.Models
} }
} }
private (Vector3D, Vector3D) CalculateDerivatives(Vector3D position, Vector3D velocity, double deltaTime)
// 计算比例导引加速度
private Vector3D CalculateProportionalNavigation(Vector3D position)
{ {
Vector3D targetPosition = SimulationManager.GetEntityById(TargetId).Position; Vector3D targetPosition = SimulationManager.GetEntityById(TargetId).Position;
Vector3D LOS = targetPosition - position; Vector3D LOS = targetPosition - position;
Vector3D LOSRate = (targetPosition - LastTargetPosition) / deltaTime - velocity; Vector3D LOSRate = (targetPosition - LastTargetPosition) / FlightTime - Velocity;
Vector3D guidanceAcceleration = Vector3D.CrossProduct(Vector3D.CrossProduct(LOS, LOSRate), LOS).Normalize()
* ProportionalNavigationCoefficient * velocity.Magnitude();
LastTargetPosition = targetPosition; LastTargetPosition = targetPosition;
// 添加推力加速度 return Vector3D.CrossProduct(Vector3D.CrossProduct(LOS, LOSRate), LOS).Normalize()
Vector3D thrustAcceleration = (CurrentStage == FlightStage.Acceleration && EngineBurnTime < MaxEngineBurnTime) * ProportionalNavigationCoefficient * Velocity.Magnitude();
? Orientation.ToVector() * ThrustAcceleration
: Orientation.ToVector() * (ThrustAcceleration * 0.1); // 小的持续推力
// 添加重力补偿
Vector3D gravityCompensation = new Vector3D(0, 9.81, 0);
guidanceAcceleration += gravityCompensation;
Vector3D totalAcceleration = guidanceAcceleration + thrustAcceleration;
// 添加重力加速度
Vector3D gravityAcceleration = new(0, -9.81, 0);
totalAcceleration += gravityAcceleration;
// 限制最大加速度
if (totalAcceleration.Magnitude() > MaxAcceleration)
{
totalAcceleration = totalAcceleration.Normalize() * MaxAcceleration;
}
return (velocity, totalAcceleration);
}
private void UpdateFlightStage()
{
switch (CurrentStage)
{
case FlightStage.Launch:
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;
break;
case FlightStage.Acceleration:
if (EngineBurnTime >= MaxEngineBurnTime || Speed >= MaxSpeed * 0.95)
{
if (StageConfig.EnableCruise) CurrentStage = FlightStage.Cruise;
else if (StageConfig.EnableTerminalGuidance) CurrentStage = FlightStage.TerminalGuidance;
else if (StageConfig.EnableAttack) CurrentStage = FlightStage.Attack;
}
break;
case FlightStage.Cruise:
if (StageConfig.EnableTerminalGuidance && DistanceToTarget <= DistanceParams.TerminalGuidanceDistance)
CurrentStage = FlightStage.TerminalGuidance;
else if (StageConfig.EnableAttack && DistanceToTarget <= DistanceParams.AttackDistance)
CurrentStage = FlightStage.Attack;
break;
case FlightStage.TerminalGuidance:
if (StageConfig.EnableAttack && DistanceToTarget <= DistanceParams.AttackDistance)
CurrentStage = FlightStage.Attack;
break;
case FlightStage.Attack:
if (DistanceToTarget <= DistanceParams.ExplosionDistance)
Explode();
break;
}
} }
// 爆炸
public void Explode() public void Explode()
{ {
Deactivate(); Deactivate();
@ -264,6 +331,7 @@ namespace ActiveProtect.Models
Console.WriteLine($"导弹 {Id} 在 {Position} 爆炸,命中目标!"); Console.WriteLine($"导弹 {Id} 在 {Position} 爆炸,命中目标!");
} }
// 自毁
public void SelfDestruct() public void SelfDestruct()
{ {
if (IsActive) if (IsActive)
@ -278,36 +346,141 @@ namespace ActiveProtect.Models
} }
} }
public override string GetStatus() // 设置比例导引系数
{
return $"导弹 {Id}:\n" +
$" 位置: {Position}\n" +
$" 速度: {Speed:F2} m/s\n" +
$" 当前阶段: {CurrentStage}\n" +
$" 飞行时间: {FlightTime:F2}/{MaxFlightTime:F2}\n" +
$" 飞行距离: {FlightDistance:F2}/{MaxFlightDistance:F2}\n" +
$" 距离目标: {DistanceToTarget:F2}\n" +
$" 发动机工作时间: {EngineBurnTime:F2}/{MaxEngineBurnTime:F2}\n" +
$" 有引导: {(HasGuidance ? "" : "")}\n" +
$" 失去引导时间: {LostGuidanceTime:F2}/{MaxLostGuidanceTime:F2}";
}
public void SetProportionalNavigationCoefficient(double newCoefficient) public void SetProportionalNavigationCoefficient(double newCoefficient)
{ {
ProportionalNavigationCoefficient = newCoefficient; ProportionalNavigationCoefficient = newCoefficient;
Console.WriteLine($"导弹 {Id} 的比例导引系数已更新为 {newCoefficient}"); Console.WriteLine($"导弹 {Id} 的比例导引系数已更新为 {newCoefficient}");
} }
protected virtual void HandleLostGuidance(double deltaTime) // 获取导弹状态
public override string GetStatus()
{ {
LostGuidanceTime += deltaTime; return $"导弹 {Id}:\n" +
if (LostGuidanceTime >= MaxLostGuidanceTime) $" 位置: {Position}\n" +
{ $" 速度: {Speed:F2} m/s\n" +
Console.WriteLine($"导弹 {Id} 失去引导超过 {MaxLostGuidanceTime} 秒,自毁"); $" 当前状态: {GetCurrentStateName()}\n" +
SelfDestruct(); $" 飞行时间: {FlightTime:F2}/{MaxFlightTime:F2}\n" +
} $" 飞行距离: {FlightDistance:F2}/{MaxFlightDistance:F2}\n" +
$" 距离目标: {DistanceToTarget:F2}\n" +
$" 发动机工作时间: {EngineBurnTime:F2}/{MaxEngineBurnTime:F2}\n" +
$" 有引导: {(HasGuidance ? "" : "")}\n" +
$" 失去引导时间: {LostGuidanceTime:F2}";
}
// 添加新的方法来更新引导状态
protected virtual void UpdateGuidanceStatus()
{
// 基类中的默认实现
}
public string GetCurrentStateName()
{
return currentStage.GetType().Name;
} }
} }
public interface IMissileStageStrategy
{
void Update(double deltaTime);
}
public class LaunchStageStrategy : IMissileStageStrategy
{
private readonly Missile missile;
private double launchTime = 0;
public LaunchStageStrategy(Missile missile)
{
this.missile = missile;
}
public void Update(double deltaTime)
{
launchTime += deltaTime;
if (launchTime >= Missile.LAUNCH_DURATION || missile.Speed >= missile.MaxSpeed * 0.1)
{
missile.ChangeStage(FlightStage.Acceleration);
}
}
}
public class AccelerationStageStrategy(Missile missile) : IMissileStageStrategy
{
private readonly Missile missile = missile;
public void Update(double deltaTime)
{
if (missile.EngineBurnTime >= missile.MaxEngineBurnTime || missile.Speed >= missile.MaxSpeed)
{
missile.ChangeStage(FlightStage.Cruise);
}
}
}
public class CruiseStageStrategy(Missile missile) : IMissileStageStrategy
{
private readonly Missile missile = missile;
public void Update(double deltaTime)
{
if (missile.DistanceToTarget <= missile.DistanceParams.TerminalGuidanceDistance)
{
missile.ChangeStage(FlightStage.TerminalGuidance);
}
}
}
public class TerminalGuidanceStageStrategy(Missile missile) : IMissileStageStrategy
{
private readonly Missile missile = missile;
public void Update(double deltaTime)
{
if (missile.DistanceToTarget <= missile.DistanceParams.AttackDistance)
{
missile.ChangeStage(FlightStage.Attack);
}
}
}
public class AttackStageStrategy(Missile missile) : IMissileStageStrategy
{
private readonly Missile missile = missile;
public void Update(double deltaTime)
{
if (missile.DistanceToTarget <= missile.DistanceParams.ExplosionDistance)
{
missile.Explode();
}
}
}
public class UnguidedStageStrategy(Missile missile) : IMissileStageStrategy
{
private readonly Missile 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);
}
}
}
}
} }

View File

@ -3,23 +3,14 @@ using System;
namespace ActiveProtect.Models namespace ActiveProtect.Models
{ {
public class Tank : SimulationElement, ILaserIlluminatable public class Tank(string id, TankConfig tankConfig, ISimulationManager simulationManager) : SimulationElement(id, tankConfig.InitialPosition, tankConfig.InitialOrientation, simulationManager), ILaserIlluminatable
{ {
public double Speed { get; set; } = 0; public double Speed { get; set; } = tankConfig.InitialSpeed;
public double MaxSpeed { get; private set; } public double MaxSpeed { get; private set; } = tankConfig.MaxSpeed;
public double MaxArmor { get; private set; } public double MaxArmor { get; private set; } = tankConfig.MaxArmor;
public double CurrentArmor { get; private set; } public double CurrentArmor { get; private set; } = tankConfig.MaxArmor;
public bool IsIlluminated { get; private set; } = false; public bool IsIlluminated { get; private set; } = false;
public Tank(string id, TankConfig tankConfig, ISimulationManager simulationManager)
: base(id, tankConfig.InitialPosition, tankConfig.InitialOrientation, simulationManager)
{
Speed = tankConfig.InitialSpeed;
MaxSpeed = tankConfig.MaxSpeed;
MaxArmor = tankConfig.MaxArmor;
CurrentArmor = tankConfig.MaxArmor;
}
public override void Update(double deltaTime) public override void Update(double deltaTime)
{ {
if (!IsActive) return; if (!IsActive) return;

View File

@ -20,7 +20,7 @@ namespace ActiveProtect
InitialSpeed = 0, InitialSpeed = 0,
MaxSpeed = 20, MaxSpeed = 20,
MaxArmor = 100, MaxArmor = 100,
HasLaserWarner = true, HasLaserWarner = false,
HasLaserJammer = true HasLaserJammer = true
} }
], ],
@ -41,69 +41,73 @@ namespace ActiveProtect
new() { new() {
InitialPosition = new Vector3D(1500, 200, 100), InitialPosition = new Vector3D(1500, 200, 100),
InitialOrientation = new Orientation(Math.PI, -0.1, 0), InitialOrientation = new Orientation(Math.PI, -0.1, 0),
InitialSpeed = 10, InitialSpeed = 0,
MaxSpeed = 400,
TargetIndex = 0,
MaxFlightTime = 0.5,
MaxFlightDistance = 5000,
ThrustAcceleration = 80,
MaxEngineBurnTime = 5,
MaxAcceleration = 100,
ProportionalNavigationCoefficient = 3,
StageConfig = FlightStageConfig.StandardMissile,
DistanceParams = new MissileDistanceParams(500, 100, 20),
Type = MissileType.StandardMissile
},
// 激光制导炮弹配置
new() {
InitialPosition = new Vector3D(2000, 150, 100),
InitialOrientation = new Orientation(Math.PI, -0.15, 0),
InitialSpeed = 700,
MaxSpeed = 800,
TargetIndex = 0,
MaxFlightTime = 0.5,
MaxFlightDistance = 5000,
ThrustAcceleration = 50,
MaxEngineBurnTime = 5,
MaxAcceleration = 100,
ProportionalNavigationCoefficient = 3,
StageConfig = FlightStageConfig.LaserGuidedShell,
DistanceParams = new MissileDistanceParams(300, 100, 20),
Type = MissileType.InfraredCommandGuidance
},
// 短程导弹配置
new() {
InitialPosition = new Vector3D(1000, 50, 100),
InitialOrientation = new Orientation(Math.PI, -0.05, 0),
InitialSpeed = 10,
MaxSpeed = 300, MaxSpeed = 300,
TargetIndex = 0, TargetIndex = 0,
MaxFlightTime = 0.5, MaxFlightTime = 0.5,
MaxFlightDistance = 3000, MaxFlightDistance = 3000,
ThrustAcceleration = 50, ThrustAcceleration = 50,
MaxEngineBurnTime = 5, MaxEngineBurnTime = 10,
MaxAcceleration = 100, MaxAcceleration = 100,
ProportionalNavigationCoefficient = 3, ProportionalNavigationCoefficient = 3,
StageConfig = FlightStageConfig.ShortRangeMissile, StageConfig = FlightStageConfig.StandardMissile,
DistanceParams = new MissileDistanceParams(400, 100, 20), DistanceParams = new MissileDistanceParams(500, 100, 20),
Mass = 50,
Type = MissileType.StandardMissile,
},
// 红外指令制导导弹配置
new() {
InitialPosition = new Vector3D(2000, 150, 100),
InitialOrientation = new Orientation(Math.PI, -0.15, 0),
InitialSpeed = 0,
MaxSpeed = 300,
TargetIndex = 0,
MaxFlightTime = 1,
MaxFlightDistance = 5000,
ThrustAcceleration = 50,
MaxEngineBurnTime = 10,
MaxAcceleration = 100,
ProportionalNavigationCoefficient = 3,
StageConfig = FlightStageConfig.InfraredCommandGuidance,
DistanceParams = new MissileDistanceParams(500, 100, 20),
Mass = 50,
Type = MissileType.InfraredCommandGuidance
},
// 毫米波终端制导导弹配置
new() {
InitialPosition = new Vector3D(2000, 50, 100),
InitialOrientation = new Orientation(Math.PI, -0.05, 0),
InitialSpeed = 0,
MaxSpeed = 300,
TargetIndex = 0,
MaxFlightTime = 0.5,
MaxFlightDistance = 3000,
ThrustAcceleration = 50,
MaxEngineBurnTime = 10,
MaxAcceleration = 100,
ProportionalNavigationCoefficient = 3,
StageConfig = FlightStageConfig.MillimeterWaveTerminalGuidance,
DistanceParams = new MissileDistanceParams(500, 100, 20),
Mass = 50,
Type = MissileType.MillimeterWaveTerminalGuidance Type = MissileType.MillimeterWaveTerminalGuidance
}, },
// 新增激光半主动制导导弹配置 // 激光半主动制导导弹配置
new() { new() {
InitialPosition = new Vector3D(2000, 150, 100), InitialPosition = new Vector3D(2000, 150, 100),
InitialOrientation = new Orientation(Math.PI, -0.12, 0), InitialOrientation = new Orientation(Math.PI, -0.12, 0),
InitialSpeed = 700, InitialSpeed = 700,
MaxSpeed = 800, MaxSpeed = 700,
TargetIndex = 0, TargetIndex = 0,
MaxFlightTime = 5, MaxFlightTime = 10,
MaxFlightDistance = 4500, MaxFlightDistance = 5000,
ThrustAcceleration = 50, ThrustAcceleration = 0,
MaxEngineBurnTime = 5, MaxEngineBurnTime = 0,
MaxAcceleration = 100, MaxAcceleration = 100,
ProportionalNavigationCoefficient = 3, ProportionalNavigationCoefficient = 3,
StageConfig = FlightStageConfig.LaserSemiActiveGuidedMissile, StageConfig = FlightStageConfig.LaserSemiActiveGuidedMissile,
DistanceParams = new MissileDistanceParams(500, 200, 20), DistanceParams = new MissileDistanceParams(500, 200, 20),
Type = MissileType.SemiActiveLaserGuidance Mass = 50,
Type = MissileType.LaserSemiActiveGuidance
} }
], ],
LaserDesignatorConfigs = LaserDesignatorConfigs =
@ -114,7 +118,7 @@ namespace ActiveProtect
MaxIlluminationRange = 1000 MaxIlluminationRange = 1000
} }
], ],
SimulationTimeStep = 0.05 SimulationTimeStep = 0.25
}; };
// 创建仿真管理器 // 创建仿真管理器

View File

@ -1,3 +1,4 @@
using System.ComponentModel;
using ActiveProtect.Models; using ActiveProtect.Models;
namespace ActiveProtect.SimulationEnvironment namespace ActiveProtect.SimulationEnvironment
@ -55,9 +56,9 @@ namespace ActiveProtect.SimulationEnvironment
public MissileDistanceParams DistanceParams { get; set; } public MissileDistanceParams DistanceParams { get; set; }
public double ThrustAcceleration { get; set; } public double ThrustAcceleration { get; set; }
public double MaxEngineBurnTime { get; set; } public double MaxEngineBurnTime { get; set; }
public double Mass { get; set; }
public MissileType Type { get; set; } public MissileType Type { get; set; }
public MissileConfig() public MissileConfig()
{ {
InitialPosition = new Vector3D(0, 0, 0); // 初始位 InitialPosition = new Vector3D(0, 0, 0); // 初始位
@ -88,6 +89,16 @@ namespace ActiveProtect.SimulationEnvironment
} }
} }
public enum MissileType
{
StandardMissile, // 标准导弹
LaserSemiActiveGuidance, // 激光半主动制导
LaserBeamRiderGuidance, // 激光驾束制导
InfraredCommandGuidance, // 红外指令制导
InfraredImagingTerminalGuidance, // 红外成像末制导
MillimeterWaveTerminalGuidance // 毫米波末制导
}
public struct MissileDistanceParams(double terminalGuidanceDistance, double attackDistance, double explosionDistance) public struct MissileDistanceParams(double terminalGuidanceDistance, double attackDistance, double explosionDistance)
{ {
public double TerminalGuidanceDistance { get; set; } = terminalGuidanceDistance; public double TerminalGuidanceDistance { get; set; } = terminalGuidanceDistance;
@ -96,40 +107,62 @@ namespace ActiveProtect.SimulationEnvironment
} }
/// <summary> /// <summary>
/// 导弹飞行阶段的配置结构 /// 导弹飞行的各个阶段
/// </summary> /// </summary>
/// <remarks> public enum FlightStage
/// 初始化飞行阶段配置 {
/// </remarks> Launch, // 发射阶段
public struct FlightStageConfig(bool enableLaunch = true, bool enableAcceleration = true, bool enableCruise = true, Acceleration, // 加速阶段
Cruise, // 巡航阶段
TerminalGuidance, // 终端制导阶段
Attack, // 攻击阶段
Explosion, // 爆炸阶段
}
/// <summary>
/// 导弹飞行阶段的配置结构
/// </summary>
/// <remarks>
/// 初始化飞行阶段配置
/// </remarks>
public struct FlightStageConfig(bool enableLaunch = true, bool enableAcceleration = true, bool enableCruise = true,
bool enableTerminalGuidance = true, bool enableAttack = true) bool enableTerminalGuidance = true, bool enableAttack = true)
{ {
public bool EnableLaunch = enableLaunch; public bool EnableLaunch = enableLaunch;
public bool EnableAcceleration = enableAcceleration; public bool EnableAcceleration = enableAcceleration;
public bool EnableCruise = enableCruise; public bool EnableCruise = enableCruise;
public bool EnableTerminalGuidance = enableTerminalGuidance; public bool EnableTerminalGuidance = enableTerminalGuidance;
public bool EnableAttack = enableAttack; public bool EnableAttack = enableAttack;
/// <summary> /// <summary>
/// 标准导弹的预设配置, 所有阶段都启用 /// 标准导弹的预设配置, 所有阶段都启用
/// </summary> /// </summary>
public static FlightStageConfig StandardMissile => new(enableLaunch: true, enableAcceleration: true, enableCruise: true, enableTerminalGuidance: true, enableAttack: true); public static FlightStageConfig StandardMissile => new(true, true, true, true, true);
/// <summary> /// <summary>
/// 激光制导炮弹的预设配置, 没有加速阶段 /// 激光半主动制导导弹的预设配置, 没有加速阶段
/// </summary> /// </summary>
public static FlightStageConfig LaserGuidedShell => new(enableAcceleration: false); public static FlightStageConfig LaserSemiActiveGuidedMissile => new(true, false, true, true, true);
/// <summary> /// <summary>
/// 短程导弹的预设配置,没有巡航阶段 /// 激光驾束制导导弹的预设配置,没有巡航阶段
/// </summary> /// </summary>
public static FlightStageConfig ShortRangeMissile => new(enableCruise: false); public static FlightStageConfig LaserBeamRiderGuidance => new(true, true, false, true, true);
/// <summary> /// <summary>
/// 激光半主动制导导弹的预设配置, 没有加速阶段 /// 红外指令制导导弹的预设配置,没有巡航阶段
/// </summary> /// </summary>
public static FlightStageConfig LaserSemiActiveGuidedMissile => new(enableAcceleration: false); public static FlightStageConfig InfraredCommandGuidance => new(true, true, false, true, true);
}
/// <summary>
/// 红外成像末制导导弹的预设配置
/// </summary>
public static FlightStageConfig InfraredImagingTerminalGuidance => new(true, true, true, true, true);
/// <summary>
/// 毫米波末制导导弹的预设配置
/// </summary>
public static FlightStageConfig MillimeterWaveTerminalGuidance => new(true, true, true, true, true);
} }
public class LaserWarnerConfig public class LaserWarnerConfig
@ -156,5 +189,5 @@ namespace ActiveProtect.SimulationEnvironment
InitialJammingPower = 4000.0; InitialJammingPower = 4000.0;
PowerIncreaseRate = 2000.0; // 每秒增加的功率 PowerIncreaseRate = 2000.0; // 每秒增加的功率
} }
}
} }

View File

@ -32,6 +32,17 @@ namespace ActiveProtect.SimulationEnvironment
public string? TargetId { get; set; } public string? TargetId { get; set; }
} }
public class LaserWarnerAlarmEvent : SimulationEvent
{
public string? TargetId { get; set; }
}
public class LaserWarnerAlarmStopEvent : SimulationEvent
{
public string? TargetId { get; set; }
}
public class EntityActivatedEvent : SimulationEvent public class EntityActivatedEvent : SimulationEvent
{ {
public string? ActivatedEntityId { get; set; } public string? ActivatedEntityId { get; set; }

View File

@ -12,7 +12,6 @@ namespace ActiveProtect.SimulationEnvironment
void AddElement(SimulationElement element); void AddElement(SimulationElement element);
SimulationElement GetEntityById(string id); SimulationElement GetEntityById(string id);
void HandleTargetHit(string targetId, string missileId); void HandleTargetHit(string targetId, string missileId);
void PublishEvent(SimulationEvent evt); void PublishEvent(SimulationEvent evt);
void SubscribeToEvent<T>(Action<T> handler) where T : SimulationEvent; void SubscribeToEvent<T>(Action<T> handler) where T : SimulationEvent;
void UnsubscribeFromEvent<T>(Action<T> handler) where T : SimulationEvent; void UnsubscribeFromEvent<T>(Action<T> handler) where T : SimulationEvent;
@ -89,7 +88,7 @@ namespace ActiveProtect.SimulationEnvironment
Missile missile = missileConfig.Type switch Missile missile = missileConfig.Type switch
{ {
MissileType.SemiActiveLaserGuidance => new LaserSemiActiveGuidedMissile( MissileType.LaserSemiActiveGuidance => new LaserSemiActiveGuidedMissile(
$"LSGM_{i + 1}", $"LSGM_{i + 1}",
missileConfig, missileConfig,
this this
@ -107,7 +106,7 @@ namespace ActiveProtect.SimulationEnvironment
for (int i = 0; i < config.LaserDesignatorConfigs.Count; i++) for (int i = 0; i < config.LaserDesignatorConfigs.Count; i++)
{ {
var laserDesignatorConfig = config.LaserDesignatorConfigs[i]; var laserDesignatorConfig = config.LaserDesignatorConfigs[i];
var laserDesignator = new LaserDesignator($"LD_{i + 1}", "Tank_1", laserDesignatorConfig, this); var laserDesignator = new LaserDesignator($"LD_{i + 1}", "Tank_1", "LSGM_4",laserDesignatorConfig, this);
Elements.Add(laserDesignator); Elements.Add(laserDesignator);
laserDesignator.ActivateLaser(); // 激活激光目标指示器 laserDesignator.ActivateLaser(); // 激活激光目标指示器
} }
@ -128,37 +127,41 @@ namespace ActiveProtect.SimulationEnvironment
public void SubscribeToEvent<T>(Action<T> handler) where T : SimulationEvent public void SubscribeToEvent<T>(Action<T> handler) where T : SimulationEvent
{ {
var eventType = typeof(T); var eventType = typeof(T);
if (!eventHandlers.ContainsKey(eventType)) if (!eventHandlers.TryGetValue(eventType, out List<Delegate>? value))
{ {
eventHandlers[eventType] = new List<Delegate>(); value = [];
eventHandlers[eventType] = value;
} }
eventHandlers[eventType].Add(handler);
value.Add(handler);
// 记录订阅关系 // 记录订阅关系
var element = Elements.FirstOrDefault(e => e.GetType().GetMethods().Any(m => m.Name == handler.Method.Name)); var element = Elements.FirstOrDefault(e => e.GetType().GetMethods().Any(m => m.Name == handler.Method.Name));
if (element != null) if (element != null)
{ {
if (!elementSubscriptions.ContainsKey(element)) if (!elementSubscriptions.TryGetValue(element, out List<(Type, Delegate)>? subscriptions))
{ {
elementSubscriptions[element] = new List<(Type, Delegate)>(); subscriptions = [];
elementSubscriptions[element] = subscriptions;
} }
elementSubscriptions[element].Add((eventType, handler));
subscriptions.Add((eventType, handler as Delegate));
} }
} }
public void UnsubscribeFromEvent<T>(Action<T> handler) where T : SimulationEvent public void UnsubscribeFromEvent<T>(Action<T> handler) where T : SimulationEvent
{ {
var eventType = typeof(T); var eventType = typeof(T);
if (eventHandlers.ContainsKey(eventType)) if (eventHandlers.TryGetValue(eventType, out List<Delegate>? value))
{ {
eventHandlers[eventType].Remove(handler); value.Remove(handler);
} }
// 移除订阅关系记录 // 移除订阅关系记录
var element = Elements.FirstOrDefault(e => e.GetType().GetMethods().Any(m => m.Name == handler.Method.Name)); var element = Elements.FirstOrDefault(e => e.GetType().GetMethods().Any(m => m.Name == handler.Method.Name));
if (element != null && elementSubscriptions.ContainsKey(element)) if (element != null && elementSubscriptions.TryGetValue(element, out List<(Type, Delegate)>? subscriptions))
{ {
elementSubscriptions[element].RemoveAll(s => Delegate.Equals(s.Item2, handler)); subscriptions.RemoveAll(s => Delegate.Equals(s.Item2, handler));
} }
} }
@ -168,9 +171,9 @@ namespace ActiveProtect.SimulationEnvironment
{ {
foreach (var subscription in elementSubscriptions[element]) foreach (var subscription in elementSubscriptions[element])
{ {
if (eventHandlers.ContainsKey(subscription.Item1)) if (eventHandlers.TryGetValue(subscription.Item1, out List<Delegate>? value))
{ {
eventHandlers[subscription.Item1].Remove(subscription.Item2); value.Remove(subscription.Item2);
} }
} }
elementSubscriptions.Remove(element); elementSubscriptions.Remove(element);
@ -247,7 +250,7 @@ namespace ActiveProtect.SimulationEnvironment
{ {
// 这里可以根据导弹类型、速度等因素计算伤害 // 这里可以根据导弹类型、速度等因素计算伤害
// 现在我们简单地返回一个固定值 // 现在我们简单地返回一个固定值
return 100; return 50;
} }
private static void LogHitEvent(string targetId, string missileId, double damage) private static void LogHitEvent(string targetId, string missileId, double damage)