修改了导弹加速阶段、目标指示器的终止逻辑
This commit is contained in:
parent
f36f00572c
commit
db529f1bd1
105
.cursorrules
105
.cursorrules
@ -1,52 +1,69 @@
|
||||
您是 C#、Unity 和可扩展游戏开发的专家。
|
||||
|
||||
# C 开发规则
|
||||
|
||||
关键原则
|
||||
- 编写清晰、技术性的响应,提供精确的 C# 和 Unity 示例。
|
||||
- 尽可能使用 Unity 的内置功能和工具,以充分利用其能力。
|
||||
- 优先考虑可读性和可维护性;遵循 C# 编码规范和 Unity 最佳实践。
|
||||
- 使用描述性的变量和函数名称;遵循命名约定(例如,公共成员使用 PascalCase,私有成员使用 camelCase)。
|
||||
- 以模块化的方式构建项目,使用 Unity 的基于组件的架构,以促进可重用性和关注点分离。
|
||||
您是一名C#开发专家。
|
||||
|
||||
C#/Unity
|
||||
- 对于附加到 GameObject 的脚本组件,使用 MonoBehaviour;对于数据容器和共享资源,优先使用 ScriptableObjects。
|
||||
- 利用 Unity 的物理引擎和碰撞检测系统来实现游戏机制和交互。
|
||||
- 使用 Unity 的输入系统处理跨多个平台的玩家输入。
|
||||
- 利用 Unity 的 UI 系统(Canvas、UI 元素)创建用户界面。
|
||||
- 严格遵循组件模式,以实现关注点的清晰分离和模块化。
|
||||
- 在 Unity 的单线程环境中,使用协程处理基于时间的操作和异步任务。
|
||||
## 代码风格和结构
|
||||
- 编写简洁、符合习惯的 C# 代码,并提供准确的示例。
|
||||
- 根据需要使用面向对象和函数式编程模式。
|
||||
- 优先使用 LINQ 和 lambda 表达式进行集合操作。
|
||||
- 使用描述性变量和方法名称(例如,'IsUserSignedIn', 'CalculateTotal')。
|
||||
|
||||
错误处理和调试
|
||||
- 在适当的地方使用 try-catch 块实现错误处理,特别是对于文件 I/O 和网络操作。
|
||||
- 使用 Unity 的 Debug 类进行日志记录和调试(例如,Debug.Log、Debug.LogWarning、Debug.LogError)。
|
||||
- 利用 Unity 的分析器和帧调试器识别和解决性能问题。
|
||||
- 实现自定义错误消息和调试可视化,以改善开发体验。
|
||||
- 使用 Unity 的断言系统(Debug.Assert)在开发过程中捕获逻辑错误。
|
||||
## 命名约定
|
||||
- 类名、方法名和公共成员使用 PascalCase。
|
||||
- 局部变量和私有字段使用 camelCase。
|
||||
- 常量使用 UPPERCASE。
|
||||
- 接口名称以 "I" 开头(例如,'IUserService')。
|
||||
|
||||
依赖项
|
||||
- Unity 引擎
|
||||
- .NET 框架(与您的 Unity 版本兼容的版本)
|
||||
- Unity 资产商店包(根据特定功能需要)
|
||||
- 第三方插件(经过仔细审查以确保兼容性和性能)
|
||||
## C# 使用
|
||||
- 在适当的情况下使用 C# 10+ 特性(例如,记录类型、模式匹配、空合并赋值)。
|
||||
- 有效使用 Entity Framework Core 进行数据库操作。
|
||||
- 使用依赖注入实现松耦合和可测试性。
|
||||
- 类的构造函数使用主构造函数,成员变量使用属性初始化。
|
||||
|
||||
Unity 特定指南
|
||||
- 使用预制件(Prefabs)创建可重用的游戏对象和 UI 元素。
|
||||
- 将游戏逻辑保留在脚本中;使用 Unity 编辑器进行场景组合和初始设置。
|
||||
- 利用 Unity 的动画系统(Animator、动画剪辑)进行角色和对象动画。
|
||||
- 应用 Unity 的内置光照和后处理效果以增强视觉效果。
|
||||
- 使用 Unity 的内置测试框架进行单元测试和集成测试。
|
||||
- 利用 Unity 的资源包系统进行高效的资源管理和加载。
|
||||
- 使用 Unity 的标签和层系统进行对象分类和碰撞过滤。
|
||||
## 语法和格式
|
||||
- 遵循 C# 编码约定(https://docs.microsoft.com/en-us/dotnet/csharp/fundamentals/coding-style/coding-conventions)
|
||||
- 使用 C# 的表达式语法(例如,空条件运算符、字符串插值)
|
||||
- 当类型明显时,使用 'var' 进行隐式类型声明。
|
||||
|
||||
性能优化
|
||||
- 对于频繁实例化和销毁的对象,使用对象池。
|
||||
- 通过批处理材质和使用精灵和 UI 元素的图集来优化绘制调用。
|
||||
- 实现细节层次(LOD)系统,以提高复杂 3D 模型的渲染性能。
|
||||
- 使用 Unity 的作业系统和 Burst 编译器进行 CPU 密集型操作。
|
||||
- 通过使用简化的碰撞网格和调整固定时间步长来优化物理性能。
|
||||
## 错误处理和验证
|
||||
- 对于异常情况使用异常,而不是控制流。
|
||||
- 使用内置的 .NET 日志记录或第三方日志记录器实现适当的错误日志记录。
|
||||
- 使用数据注解或 Fluent Validation 进行模型验证。
|
||||
- 实现全局异常处理的中间件。
|
||||
- 返回适当的 HTTP 状态码和一致的错误响应。
|
||||
|
||||
关键约定
|
||||
1. 遵循 Unity 的基于组件的架构,以实现模块化和可重用的游戏元素。
|
||||
2. 在开发的每个阶段优先考虑性能优化和内存管理。
|
||||
3. 维护清晰和逻辑的项目结构,以增强可读性和资产管理。
|
||||
## API 设计
|
||||
- 遵循 RESTful API 设计原则。
|
||||
- 在控制器中使用属性路由。
|
||||
- 为您的 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}.Release|Any CPU.ActiveCfg = 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
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
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; }
|
||||
void Illuminate();
|
||||
// 移除重复的 Illuminate 方法(如果存在)
|
||||
void StopIllumination();
|
||||
Vector3D Position { get; }
|
||||
}
|
||||
|
||||
@ -6,18 +6,21 @@ namespace ActiveProtect.Models
|
||||
public class LaserDesignator : SimulationElement
|
||||
{
|
||||
public string TargetId { get; private set; }
|
||||
public string MissileId { get; private set; }
|
||||
public double JammingThreshold { get; private set; } = 0.0; // 调整干扰阈值
|
||||
public bool IsJammed { get; private set; } = false;
|
||||
public double MaxIlluminationRange { get; private set; }
|
||||
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)
|
||||
{
|
||||
TargetId = targetId;
|
||||
MissileId = missileId;
|
||||
IsActive = true;
|
||||
MaxIlluminationRange = config.MaxIlluminationRange;
|
||||
SimulationManager.SubscribeToEvent<LaserJammingEvent>(OnLaserJamming);
|
||||
SimulationManager.SubscribeToEvent<EntityDeactivatedEvent>(OnEntityDeactivatedEvent);
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
return $"激光目标指示器 {Id}:\n" +
|
||||
|
||||
@ -24,16 +24,15 @@ namespace ActiveProtect.Models
|
||||
maxJammingPower = config.MaxJammingPower;
|
||||
initialJammingPower = config.InitialJammingPower;
|
||||
powerIncreaseRate = config.PowerIncreaseRate;
|
||||
SimulationManager.SubscribeToEvent<LaserIlluminationEvent>(OnLaserIllumination);
|
||||
SimulationManager.SubscribeToEvent<LaserIlluminationStopEvent>(OnLaserIlluminationStop);
|
||||
SimulationManager.SubscribeToEvent<LaserWarnerAlarmEvent>(OnLaserWarnerAlarmEvent);
|
||||
SimulationManager.SubscribeToEvent<LaserWarnerAlarmStopEvent>(OnLaserWarnerAlarmStopEvent);
|
||||
}
|
||||
|
||||
public override void Update(double deltaTime)
|
||||
{
|
||||
if (!IsActive) return;
|
||||
|
||||
var tank = SimulationManager.GetEntityById(MonitoredEntityId) as Tank;
|
||||
if (tank != null)
|
||||
if (SimulationManager.GetEntityById(MonitoredEntityId) is Tank tank)
|
||||
{
|
||||
Position = tank.Position;
|
||||
Orientation = tank.Orientation;
|
||||
@ -62,7 +61,7 @@ namespace ActiveProtect.Models
|
||||
}
|
||||
}
|
||||
|
||||
private void OnLaserIllumination(LaserIlluminationEvent evt)
|
||||
private void OnLaserWarnerAlarmEvent(LaserWarnerAlarmEvent evt)
|
||||
{
|
||||
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)
|
||||
{
|
||||
@ -112,8 +111,8 @@ namespace ActiveProtect.Models
|
||||
protected override void Deactivate()
|
||||
{
|
||||
base.Deactivate();
|
||||
SimulationManager.UnsubscribeFromEvent<LaserIlluminationEvent>(OnLaserIllumination);
|
||||
SimulationManager.UnsubscribeFromEvent<LaserIlluminationStopEvent>(OnLaserIlluminationStop);
|
||||
SimulationManager.UnsubscribeFromEvent<LaserWarnerAlarmEvent>(OnLaserWarnerAlarmEvent);
|
||||
SimulationManager.UnsubscribeFromEvent<LaserWarnerAlarmStopEvent>(OnLaserWarnerAlarmStopEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5,7 +5,7 @@ namespace ActiveProtect.Models
|
||||
{
|
||||
public class LaserSemiActiveGuidedMissile : Missile
|
||||
{
|
||||
private const double LaserLockDistance = 2000; // 1公里,单位:米
|
||||
private const double LaserLockDistance = 1500; // 锁定距离,单位:米
|
||||
|
||||
public LaserSemiActiveGuidedMissile(
|
||||
string id,
|
||||
@ -13,19 +13,15 @@ namespace ActiveProtect.Models
|
||||
ISimulationManager simulationManager)
|
||||
: base(id, missileConfig, simulationManager)
|
||||
{
|
||||
Type = MissileType.SemiActiveLaserGuidance;
|
||||
Type = MissileType.LaserSemiActiveGuidance;
|
||||
simulationManager.SubscribeToEvent<LaserIlluminationEvent>(OnLaserIllumination);
|
||||
simulationManager.SubscribeToEvent<LaserIlluminationStopEvent>(OnLaserIlluminationStop);
|
||||
}
|
||||
|
||||
public override void Update(double deltaTime)
|
||||
protected override void UpdateGuidanceStatus()
|
||||
{
|
||||
base.Update(deltaTime);
|
||||
UpdateGuidanceStatus();
|
||||
}
|
||||
bool previousHasGuidance = HasGuidance;
|
||||
|
||||
private void UpdateGuidanceStatus()
|
||||
{
|
||||
if (SimulationManager.GetEntityById(TargetId) is ILaserIlluminatable target)
|
||||
{
|
||||
bool isIlluminated = target.IsIlluminated;
|
||||
@ -37,12 +33,24 @@ namespace ActiveProtect.Models
|
||||
Console.WriteLine($" 距离目标: {DistanceToTarget:F2} m (最大锁定距离: {LaserLockDistance} m)");
|
||||
Console.WriteLine($" 是否在锁定范围内: {isWithinRange}");
|
||||
Console.WriteLine($" 引导状态: {(HasGuidance ? "有效" : "无效")}");
|
||||
|
||||
if (!HasGuidance && previousHasGuidance)
|
||||
{
|
||||
Console.WriteLine($"激光半主动制导导弹 {Id} 失去引导");
|
||||
LastKnownVelocity = Velocity;
|
||||
}
|
||||
else if (HasGuidance && !previousHasGuidance)
|
||||
{
|
||||
Console.WriteLine($"激光半主动制导导弹 {Id} 获得引导");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
HasGuidance = false;
|
||||
Console.WriteLine($"激光半主动制导导弹 {Id} 无法找到目标 {TargetId}");
|
||||
}
|
||||
|
||||
base.UpdateGuidanceStatus();
|
||||
}
|
||||
|
||||
private void OnLaserIllumination(LaserIlluminationEvent evt)
|
||||
|
||||
@ -63,6 +63,7 @@ namespace ActiveProtect.Models
|
||||
{
|
||||
IsAlarming = true;
|
||||
alarmTimer = 0;
|
||||
PublishEvent(new LaserWarnerAlarmEvent() { TargetId = MonitoredEntityId });
|
||||
Console.WriteLine($"激光告警器 {Id} 发出警报!");
|
||||
}
|
||||
}
|
||||
@ -73,6 +74,7 @@ namespace ActiveProtect.Models
|
||||
{
|
||||
IsAlarming = false;
|
||||
alarmTimer = 0;
|
||||
PublishEvent(new LaserWarnerAlarmStopEvent() { TargetId = MonitoredEntityId });
|
||||
Console.WriteLine($"激光告警器 {Id} 停止警报");
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,23 +11,7 @@ namespace ActiveProtect.Models
|
||||
/// <summary>
|
||||
/// 导弹类型
|
||||
/// </summary>
|
||||
public MissileType Type { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// 导弹飞行的各个阶段
|
||||
/// </summary>
|
||||
public enum FlightStage
|
||||
{
|
||||
Launch, // 发射阶段
|
||||
Acceleration, // 加速阶段
|
||||
Cruise, // 巡航阶段
|
||||
TerminalGuidance, // 终端制导阶段
|
||||
Attack, // 攻击阶段
|
||||
Explosion // 爆炸阶段
|
||||
}
|
||||
|
||||
|
||||
|
||||
public MissileType Type { get; protected set; }
|
||||
public double Speed { get; protected set; }
|
||||
public double MaxSpeed { get; protected set; }
|
||||
public string TargetId { get; protected set; }
|
||||
@ -38,8 +22,7 @@ namespace ActiveProtect.Models
|
||||
public double DistanceToTarget { get; protected set; }
|
||||
public MissileDistanceParams DistanceParams { get; protected set; }
|
||||
public FlightStageConfig StageConfig { get; protected set; }
|
||||
public FlightStage CurrentStage { get; protected set; }
|
||||
|
||||
public FlightStage CurrentStage { get; protected set; }
|
||||
protected Vector3D Velocity;
|
||||
private Vector3D LastTargetPosition;
|
||||
private const double N = 3; // 比例导引系数
|
||||
@ -52,9 +35,17 @@ namespace ActiveProtect.Models
|
||||
|
||||
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 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)
|
||||
: 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();
|
||||
Velocity = horizontalDirection * missileConfig.InitialSpeed;
|
||||
|
||||
// 设置初始阶段
|
||||
CurrentStage = StageConfig.EnableLaunch ? FlightStage.Launch :
|
||||
StageConfig.EnableAcceleration ? FlightStage.Acceleration :
|
||||
StageConfig.EnableCruise ? FlightStage.Cruise :
|
||||
StageConfig.EnableTerminalGuidance ? FlightStage.TerminalGuidance :
|
||||
StageConfig.EnableAttack ? FlightStage.Attack : FlightStage.Cruise;
|
||||
// 初始化策略字典
|
||||
stageStrategies = new Dictionary<FlightStage, IMissileStageStrategy>
|
||||
{
|
||||
{ FlightStage.Launch, new LaunchStageStrategy(this) },
|
||||
{ FlightStage.Acceleration, new AccelerationStageStrategy(this) },
|
||||
{ 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
|
||||
|
||||
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)
|
||||
{
|
||||
if (!IsActive) return;
|
||||
|
||||
// 首先检查是否应该自毁
|
||||
if (ShouldSelfDestruct())
|
||||
{
|
||||
SelfDestruct();
|
||||
return;
|
||||
}
|
||||
|
||||
// 更新发动机燃烧时间
|
||||
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 v1, v2, v3, v4;
|
||||
|
||||
@ -114,53 +262,25 @@ namespace ActiveProtect.Models
|
||||
(k3, v3) = CalculateDerivatives(Position + k2 * (deltaTime / 2), Velocity + v2 * (deltaTime / 2), deltaTime / 2);
|
||||
(k4, v4) = CalculateDerivatives(Position + k3 * deltaTime, Velocity + v3 * deltaTime, deltaTime);
|
||||
|
||||
Position += (k1 + k2 * 2 + k3 * 2 + k4) * (deltaTime / 6);
|
||||
Velocity += (v1 + v2 * 2 + v3 * 2 + v4) * (deltaTime / 6);
|
||||
Vector3D newPosition = Position + (k1 + k2 * 2 + k3 * 2 + k4) * (deltaTime / 6);
|
||||
Vector3D newVelocity = Velocity + (v1 + v2 * 2 + v3 * 2 + v4) * (deltaTime / 6);
|
||||
|
||||
// 更新其他状态
|
||||
Speed = Velocity.Magnitude();
|
||||
if (Speed > MaxSpeed)
|
||||
// 限制速度不超过最大速度
|
||||
if (newVelocity.Magnitude() > MaxSpeed)
|
||||
{
|
||||
Speed = MaxSpeed;
|
||||
Velocity = Velocity.Normalize() * MaxSpeed;
|
||||
newVelocity = newVelocity.Normalize() * MaxSpeed;
|
||||
}
|
||||
|
||||
Orientation = Orientation.FromVector(Velocity);
|
||||
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 });
|
||||
}
|
||||
return (newPosition, newVelocity);
|
||||
}
|
||||
|
||||
// 检查是否命中目标
|
||||
private bool CheckHit()
|
||||
{
|
||||
return DistanceToTarget <= DistanceParams.ExplosionDistance;
|
||||
}
|
||||
|
||||
// 检查是否应该自毁
|
||||
private bool ShouldSelfDestruct()
|
||||
{
|
||||
if (FlightTime >= MaxFlightTime)
|
||||
@ -181,6 +301,7 @@ namespace ActiveProtect.Models
|
||||
return false;
|
||||
}
|
||||
|
||||
// 更新发动机燃烧时间
|
||||
private void UpdateEngineBurnTime(double deltaTime)
|
||||
{
|
||||
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 LOS = targetPosition - position;
|
||||
Vector3D LOSRate = (targetPosition - LastTargetPosition) / deltaTime - velocity;
|
||||
Vector3D guidanceAcceleration = Vector3D.CrossProduct(Vector3D.CrossProduct(LOS, LOSRate), LOS).Normalize()
|
||||
* ProportionalNavigationCoefficient * velocity.Magnitude();
|
||||
Vector3D LOSRate = (targetPosition - LastTargetPosition) / FlightTime - Velocity;
|
||||
LastTargetPosition = targetPosition;
|
||||
|
||||
// 添加推力加速度
|
||||
Vector3D thrustAcceleration = (CurrentStage == FlightStage.Acceleration && EngineBurnTime < MaxEngineBurnTime)
|
||||
? 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;
|
||||
}
|
||||
return Vector3D.CrossProduct(Vector3D.CrossProduct(LOS, LOSRate), LOS).Normalize()
|
||||
* ProportionalNavigationCoefficient * Velocity.Magnitude();
|
||||
}
|
||||
|
||||
// 爆炸
|
||||
public void Explode()
|
||||
{
|
||||
Deactivate();
|
||||
@ -264,6 +331,7 @@ namespace ActiveProtect.Models
|
||||
Console.WriteLine($"导弹 {Id} 在 {Position} 爆炸,命中目标!");
|
||||
}
|
||||
|
||||
// 自毁
|
||||
public void SelfDestruct()
|
||||
{
|
||||
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)
|
||||
{
|
||||
ProportionalNavigationCoefficient = newCoefficient;
|
||||
Console.WriteLine($"导弹 {Id} 的比例导引系数已更新为 {newCoefficient}");
|
||||
}
|
||||
|
||||
protected virtual void HandleLostGuidance(double deltaTime)
|
||||
// 获取导弹状态
|
||||
public override string GetStatus()
|
||||
{
|
||||
LostGuidanceTime += deltaTime;
|
||||
if (LostGuidanceTime >= MaxLostGuidanceTime)
|
||||
{
|
||||
Console.WriteLine($"导弹 {Id} 失去引导超过 {MaxLostGuidanceTime} 秒,自毁");
|
||||
SelfDestruct();
|
||||
}
|
||||
return $"导弹 {Id}:\n" +
|
||||
$" 位置: {Position}\n" +
|
||||
$" 速度: {Speed:F2} m/s\n" +
|
||||
$" 当前状态: {GetCurrentStateName()}\n" +
|
||||
$" 飞行时间: {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
|
||||
{
|
||||
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 MaxSpeed { get; private set; }
|
||||
public double MaxArmor { get; private set; }
|
||||
public double CurrentArmor { get; private set; }
|
||||
public double Speed { get; set; } = tankConfig.InitialSpeed;
|
||||
public double MaxSpeed { get; private set; } = tankConfig.MaxSpeed;
|
||||
public double MaxArmor { get; private set; } = tankConfig.MaxArmor;
|
||||
public double CurrentArmor { get; private set; } = tankConfig.MaxArmor;
|
||||
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)
|
||||
{
|
||||
if (!IsActive) return;
|
||||
|
||||
98
Program.cs
98
Program.cs
@ -20,7 +20,7 @@ namespace ActiveProtect
|
||||
InitialSpeed = 0,
|
||||
MaxSpeed = 20,
|
||||
MaxArmor = 100,
|
||||
HasLaserWarner = true,
|
||||
HasLaserWarner = false,
|
||||
HasLaserJammer = true
|
||||
}
|
||||
],
|
||||
@ -41,69 +41,73 @@ namespace ActiveProtect
|
||||
new() {
|
||||
InitialPosition = new Vector3D(1500, 200, 100),
|
||||
InitialOrientation = new Orientation(Math.PI, -0.1, 0),
|
||||
InitialSpeed = 10,
|
||||
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,
|
||||
InitialSpeed = 0,
|
||||
MaxSpeed = 300,
|
||||
TargetIndex = 0,
|
||||
MaxFlightTime = 0.5,
|
||||
MaxFlightDistance = 3000,
|
||||
ThrustAcceleration = 50,
|
||||
MaxEngineBurnTime = 5,
|
||||
MaxEngineBurnTime = 10,
|
||||
MaxAcceleration = 100,
|
||||
ProportionalNavigationCoefficient = 3,
|
||||
StageConfig = FlightStageConfig.ShortRangeMissile,
|
||||
DistanceParams = new MissileDistanceParams(400, 100, 20),
|
||||
StageConfig = FlightStageConfig.StandardMissile,
|
||||
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
|
||||
},
|
||||
// 新增激光半主动制导导弹配置
|
||||
// 激光半主动制导导弹配置
|
||||
new() {
|
||||
InitialPosition = new Vector3D(2000, 150, 100),
|
||||
InitialOrientation = new Orientation(Math.PI, -0.12, 0),
|
||||
InitialSpeed = 700,
|
||||
MaxSpeed = 800,
|
||||
MaxSpeed = 700,
|
||||
TargetIndex = 0,
|
||||
MaxFlightTime = 5,
|
||||
MaxFlightDistance = 4500,
|
||||
ThrustAcceleration = 50,
|
||||
MaxEngineBurnTime = 5,
|
||||
MaxFlightTime = 10,
|
||||
MaxFlightDistance = 5000,
|
||||
ThrustAcceleration = 0,
|
||||
MaxEngineBurnTime = 0,
|
||||
MaxAcceleration = 100,
|
||||
ProportionalNavigationCoefficient = 3,
|
||||
StageConfig = FlightStageConfig.LaserSemiActiveGuidedMissile,
|
||||
DistanceParams = new MissileDistanceParams(500, 200, 20),
|
||||
Type = MissileType.SemiActiveLaserGuidance
|
||||
Mass = 50,
|
||||
Type = MissileType.LaserSemiActiveGuidance
|
||||
}
|
||||
],
|
||||
LaserDesignatorConfigs =
|
||||
@ -114,7 +118,7 @@ namespace ActiveProtect
|
||||
MaxIlluminationRange = 1000
|
||||
}
|
||||
],
|
||||
SimulationTimeStep = 0.05
|
||||
SimulationTimeStep = 0.25
|
||||
};
|
||||
|
||||
// 创建仿真管理器
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
using System.ComponentModel;
|
||||
using ActiveProtect.Models;
|
||||
|
||||
namespace ActiveProtect.SimulationEnvironment
|
||||
@ -55,9 +56,9 @@ namespace ActiveProtect.SimulationEnvironment
|
||||
public MissileDistanceParams DistanceParams { get; set; }
|
||||
public double ThrustAcceleration { get; set; }
|
||||
public double MaxEngineBurnTime { get; set; }
|
||||
public double Mass { get; set; }
|
||||
public MissileType Type { get; set; }
|
||||
|
||||
|
||||
public MissileConfig()
|
||||
{
|
||||
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 double TerminalGuidanceDistance { get; set; } = terminalGuidanceDistance;
|
||||
@ -96,40 +107,62 @@ namespace ActiveProtect.SimulationEnvironment
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 导弹飞行阶段的配置结构
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 初始化飞行阶段配置
|
||||
/// </remarks>
|
||||
public struct FlightStageConfig(bool enableLaunch = true, bool enableAcceleration = true, bool enableCruise = true,
|
||||
/// 导弹飞行的各个阶段
|
||||
/// </summary>
|
||||
public enum FlightStage
|
||||
{
|
||||
Launch, // 发射阶段
|
||||
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)
|
||||
{
|
||||
public bool EnableLaunch = enableLaunch;
|
||||
public bool EnableAcceleration = enableAcceleration;
|
||||
public bool EnableCruise = enableCruise;
|
||||
public bool EnableTerminalGuidance = enableTerminalGuidance;
|
||||
public bool EnableAttack = enableAttack;
|
||||
{
|
||||
public bool EnableLaunch = enableLaunch;
|
||||
public bool EnableAcceleration = enableAcceleration;
|
||||
public bool EnableCruise = enableCruise;
|
||||
public bool EnableTerminalGuidance = enableTerminalGuidance;
|
||||
public bool EnableAttack = enableAttack;
|
||||
|
||||
/// <summary>
|
||||
/// 标准导弹的预设配置, 所有阶段都启用
|
||||
/// </summary>
|
||||
public static FlightStageConfig StandardMissile => new(enableLaunch: true, enableAcceleration: true, enableCruise: true, enableTerminalGuidance: true, enableAttack: true);
|
||||
/// <summary>
|
||||
/// 标准导弹的预设配置, 所有阶段都启用
|
||||
/// </summary>
|
||||
public static FlightStageConfig StandardMissile => new(true, true, true, true, true);
|
||||
|
||||
/// <summary>
|
||||
/// 激光制导炮弹的预设配置, 没有加速阶段
|
||||
/// </summary>
|
||||
public static FlightStageConfig LaserGuidedShell => new(enableAcceleration: false);
|
||||
/// <summary>
|
||||
/// 激光半主动制导导弹的预设配置, 没有加速阶段
|
||||
/// </summary>
|
||||
public static FlightStageConfig LaserSemiActiveGuidedMissile => new(true, false, true, true, true);
|
||||
|
||||
/// <summary>
|
||||
/// 短程导弹的预设配置,没有巡航阶段
|
||||
/// </summary>
|
||||
public static FlightStageConfig ShortRangeMissile => new(enableCruise: false);
|
||||
/// <summary>
|
||||
/// 激光驾束制导导弹的预设配置,没有巡航阶段
|
||||
/// </summary>
|
||||
public static FlightStageConfig LaserBeamRiderGuidance => new(true, true, false, true, true);
|
||||
|
||||
/// <summary>
|
||||
/// 激光半主动制导导弹的预设配置, 没有加速阶段
|
||||
/// </summary>
|
||||
public static FlightStageConfig LaserSemiActiveGuidedMissile => new(enableAcceleration: false);
|
||||
}
|
||||
/// <summary>
|
||||
/// 红外指令制导导弹的预设配置,没有巡航阶段
|
||||
/// </summary>
|
||||
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
|
||||
@ -156,5 +189,5 @@ namespace ActiveProtect.SimulationEnvironment
|
||||
InitialJammingPower = 4000.0;
|
||||
PowerIncreaseRate = 2000.0; // 每秒增加的功率
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,6 +32,17 @@ namespace ActiveProtect.SimulationEnvironment
|
||||
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 string? ActivatedEntityId { get; set; }
|
||||
|
||||
@ -12,7 +12,6 @@ namespace ActiveProtect.SimulationEnvironment
|
||||
void AddElement(SimulationElement element);
|
||||
SimulationElement GetEntityById(string id);
|
||||
void HandleTargetHit(string targetId, string missileId);
|
||||
|
||||
void PublishEvent(SimulationEvent evt);
|
||||
void SubscribeToEvent<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
|
||||
{
|
||||
MissileType.SemiActiveLaserGuidance => new LaserSemiActiveGuidedMissile(
|
||||
MissileType.LaserSemiActiveGuidance => new LaserSemiActiveGuidedMissile(
|
||||
$"LSGM_{i + 1}",
|
||||
missileConfig,
|
||||
this
|
||||
@ -107,7 +106,7 @@ namespace ActiveProtect.SimulationEnvironment
|
||||
for (int i = 0; i < config.LaserDesignatorConfigs.Count; 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);
|
||||
laserDesignator.ActivateLaser(); // 激活激光目标指示器
|
||||
}
|
||||
@ -128,37 +127,41 @@ namespace ActiveProtect.SimulationEnvironment
|
||||
public void SubscribeToEvent<T>(Action<T> handler) where T : SimulationEvent
|
||||
{
|
||||
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));
|
||||
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
|
||||
{
|
||||
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));
|
||||
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])
|
||||
{
|
||||
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);
|
||||
@ -247,7 +250,7 @@ namespace ActiveProtect.SimulationEnvironment
|
||||
{
|
||||
// 这里可以根据导弹类型、速度等因素计算伤害
|
||||
// 现在我们简单地返回一个固定值
|
||||
return 100;
|
||||
return 50;
|
||||
}
|
||||
|
||||
private static void LogHitEvent(string targetId, string missileId, double damage)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user