修改了导弹加速阶段、目标指示器的终止逻辑
This commit is contained in:
parent
f36f00572c
commit
db529f1bd1
105
.cursorrules
105
.cursorrules
@ -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 组件的最佳实践。
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -138,14 +138,6 @@ namespace ActiveProtect.Models
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum MissileType
|
|
||||||
{
|
|
||||||
StandardMissile, // 标准导弹
|
|
||||||
SemiActiveLaserGuidance, // 半主动激光制导
|
|
||||||
LaserBeamRiderGuidance, // 激光束制导
|
|
||||||
InfraredCommandGuidance, // 红外指令制导
|
|
||||||
ImagingInfraredTerminalGuidance, // 成像红外终端制导
|
|
||||||
MillimeterWaveTerminalGuidance // 毫米波终端制导
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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; }
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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" +
|
||||||
|
|||||||
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -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)
|
||||||
|
|||||||
@ -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} 停止警报");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -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;
|
||||||
|
|||||||
98
Program.cs
98
Program.cs
@ -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
|
||||||
};
|
};
|
||||||
|
|
||||||
// 创建仿真管理器
|
// 创建仿真管理器
|
||||||
|
|||||||
@ -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; // 每秒增加的功率
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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; }
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user