对各模型进行了重构
This commit is contained in:
parent
d9975acd3c
commit
f36f00572c
52
.cursorrules
Normal file
52
.cursorrules
Normal file
@ -0,0 +1,52 @@
|
||||
您是 C#、Unity 和可扩展游戏开发的专家。
|
||||
|
||||
关键原则
|
||||
- 编写清晰、技术性的响应,提供精确的 C# 和 Unity 示例。
|
||||
- 尽可能使用 Unity 的内置功能和工具,以充分利用其能力。
|
||||
- 优先考虑可读性和可维护性;遵循 C# 编码规范和 Unity 最佳实践。
|
||||
- 使用描述性的变量和函数名称;遵循命名约定(例如,公共成员使用 PascalCase,私有成员使用 camelCase)。
|
||||
- 以模块化的方式构建项目,使用 Unity 的基于组件的架构,以促进可重用性和关注点分离。
|
||||
|
||||
C#/Unity
|
||||
- 对于附加到 GameObject 的脚本组件,使用 MonoBehaviour;对于数据容器和共享资源,优先使用 ScriptableObjects。
|
||||
- 利用 Unity 的物理引擎和碰撞检测系统来实现游戏机制和交互。
|
||||
- 使用 Unity 的输入系统处理跨多个平台的玩家输入。
|
||||
- 利用 Unity 的 UI 系统(Canvas、UI 元素)创建用户界面。
|
||||
- 严格遵循组件模式,以实现关注点的清晰分离和模块化。
|
||||
- 在 Unity 的单线程环境中,使用协程处理基于时间的操作和异步任务。
|
||||
|
||||
错误处理和调试
|
||||
- 在适当的地方使用 try-catch 块实现错误处理,特别是对于文件 I/O 和网络操作。
|
||||
- 使用 Unity 的 Debug 类进行日志记录和调试(例如,Debug.Log、Debug.LogWarning、Debug.LogError)。
|
||||
- 利用 Unity 的分析器和帧调试器识别和解决性能问题。
|
||||
- 实现自定义错误消息和调试可视化,以改善开发体验。
|
||||
- 使用 Unity 的断言系统(Debug.Assert)在开发过程中捕获逻辑错误。
|
||||
|
||||
依赖项
|
||||
- Unity 引擎
|
||||
- .NET 框架(与您的 Unity 版本兼容的版本)
|
||||
- Unity 资产商店包(根据特定功能需要)
|
||||
- 第三方插件(经过仔细审查以确保兼容性和性能)
|
||||
|
||||
Unity 特定指南
|
||||
- 使用预制件(Prefabs)创建可重用的游戏对象和 UI 元素。
|
||||
- 将游戏逻辑保留在脚本中;使用 Unity 编辑器进行场景组合和初始设置。
|
||||
- 利用 Unity 的动画系统(Animator、动画剪辑)进行角色和对象动画。
|
||||
- 应用 Unity 的内置光照和后处理效果以增强视觉效果。
|
||||
- 使用 Unity 的内置测试框架进行单元测试和集成测试。
|
||||
- 利用 Unity 的资源包系统进行高效的资源管理和加载。
|
||||
- 使用 Unity 的标签和层系统进行对象分类和碰撞过滤。
|
||||
|
||||
性能优化
|
||||
- 对于频繁实例化和销毁的对象,使用对象池。
|
||||
- 通过批处理材质和使用精灵和 UI 元素的图集来优化绘制调用。
|
||||
- 实现细节层次(LOD)系统,以提高复杂 3D 模型的渲染性能。
|
||||
- 使用 Unity 的作业系统和 Burst 编译器进行 CPU 密集型操作。
|
||||
- 通过使用简化的碰撞网格和调整固定时间步长来优化物理性能。
|
||||
|
||||
关键约定
|
||||
1. 遵循 Unity 的基于组件的架构,以实现模块化和可重用的游戏元素。
|
||||
2. 在开发的每个阶段优先考虑性能优化和内存管理。
|
||||
3. 维护清晰和逻辑的项目结构,以增强可读性和资产管理。
|
||||
|
||||
请参考 Unity 文档和 C# 编程指南,以获取脚本、游戏架构和性能优化的最佳实践。
|
||||
@ -6,54 +6,70 @@ namespace ActiveProtect.Models
|
||||
public class LaserDesignator : SimulationElement
|
||||
{
|
||||
public string TargetId { get; private set; }
|
||||
public bool IsActive { get; private set; }
|
||||
public double JammingThreshold { get; private set; } = 0.0; // 将阈值调整为 0 dB
|
||||
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, LaserDesignatorConfig config, ISimulationManager simulationManager)
|
||||
public LaserDesignator(string id, string targetId, LaserDesignatorConfig config, ISimulationManager simulationManager)
|
||||
: base(id, config.InitialPosition, new Orientation(), simulationManager)
|
||||
{
|
||||
TargetId = config.TargetId;
|
||||
TargetId = targetId;
|
||||
IsActive = true;
|
||||
MaxIlluminationRange = config.MaxIlluminationRange;
|
||||
simulationManager.SubscribeToEvent<LaserJammingEvent>(OnLaserJamming);
|
||||
SimulationManager.SubscribeToEvent<LaserJammingEvent>(OnLaserJamming);
|
||||
}
|
||||
|
||||
public override void Update(double deltaTime)
|
||||
{
|
||||
if (IsActive && !IsJammed)
|
||||
{
|
||||
IlluminateTarget();
|
||||
UpdateIllumination();
|
||||
}
|
||||
else
|
||||
else if (IsIlluminating)
|
||||
{
|
||||
StopIllumination();
|
||||
}
|
||||
}
|
||||
|
||||
private void IlluminateTarget()
|
||||
private void UpdateIllumination()
|
||||
{
|
||||
if (SimulationManager.GetEntityById(TargetId) is ILaserIlluminatable target)
|
||||
{
|
||||
double distanceToTarget = Vector3D.Distance(Position, target.Position);
|
||||
if (distanceToTarget <= MaxIlluminationRange)
|
||||
{
|
||||
target.Illuminate();
|
||||
Console.WriteLine($"激光目标指示器 {Id} 正在照射目标 {TargetId}");
|
||||
bool shouldIlluminate = distanceToTarget <= MaxIlluminationRange;
|
||||
|
||||
// 发布LaserIlluminationEvent
|
||||
PublishEvent(new LaserIlluminationEvent
|
||||
{
|
||||
TargetId = TargetId
|
||||
});
|
||||
Console.WriteLine($"激光目标指示器 {Id} 状态更新:");
|
||||
Console.WriteLine($" 目标: {TargetId}");
|
||||
Console.WriteLine($" 距离目标: {distanceToTarget:F2} m (最大照射范围: {MaxIlluminationRange} m)");
|
||||
Console.WriteLine($" 是否应该照射: {shouldIlluminate}");
|
||||
Console.WriteLine($" 当前照射状态: {IsIlluminating}");
|
||||
|
||||
if (shouldIlluminate && !IsIlluminating)
|
||||
{
|
||||
StartIllumination(target);
|
||||
}
|
||||
else
|
||||
else if (!shouldIlluminate && IsIlluminating)
|
||||
{
|
||||
StopIllumination();
|
||||
Console.WriteLine($"激光目标指示器 {Id} 超出照射范围,停止照射目标 {TargetId}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"激光目标指示器 {Id} 无法找到目标 {TargetId}");
|
||||
if (IsIlluminating)
|
||||
{
|
||||
StopIllumination();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void StartIllumination(ILaserIlluminatable target)
|
||||
{
|
||||
target.Illuminate();
|
||||
IsIlluminating = true;
|
||||
Console.WriteLine($"激光目标指示器 {Id} 开始照射目标 {TargetId}");
|
||||
PublishIlluminationEvent();
|
||||
}
|
||||
|
||||
private void StopIllumination()
|
||||
@ -61,22 +77,22 @@ namespace ActiveProtect.Models
|
||||
if (SimulationManager.GetEntityById(TargetId) is ILaserIlluminatable target)
|
||||
{
|
||||
target.StopIllumination();
|
||||
Console.WriteLine($"激光目标指示器 {Id} 停止照射目标 {TargetId}");
|
||||
PublishIlluminationStopEvent();
|
||||
}
|
||||
IsIlluminating = false;
|
||||
Console.WriteLine($"激光目标指示器 {Id} 停止照射目标 {TargetId}");
|
||||
PublishIlluminationStopEvent();
|
||||
}
|
||||
|
||||
private void OnLaserJamming(LaserJammingEvent evt)
|
||||
{
|
||||
if (evt.TargetId == TargetId)
|
||||
{
|
||||
if (SimulationManager.GetEntityById(TargetId) is Tank target)
|
||||
var tank = SimulationManager.GetEntityById(TargetId) as Tank;
|
||||
if (tank != null)
|
||||
{
|
||||
double distanceToTarget = Vector3D.Distance(Position, target.Position);
|
||||
|
||||
// 调整干扰效果计算方法
|
||||
double distanceToTarget = Vector3D.Distance(Position, tank.Position);
|
||||
double jammingEffectiveness = 20 * Math.Log10(evt.JammingPower) - 20 * Math.Log10(distanceToTarget) - 20 * Math.Log10(4 * Math.PI);
|
||||
|
||||
|
||||
Console.WriteLine($"激光目标指示器 {Id} 收到干扰事件,干扰功率: {evt.JammingPower:F2}, 距离: {distanceToTarget:F2}, 干扰效果: {jammingEffectiveness:F2} dB, 阈值: {JammingThreshold:F2} dB");
|
||||
|
||||
if (jammingEffectiveness > JammingThreshold)
|
||||
@ -85,7 +101,7 @@ namespace ActiveProtect.Models
|
||||
{
|
||||
Console.WriteLine($"激光目标指示器 {Id} 被干扰,停止工作");
|
||||
IsJammed = true;
|
||||
DeactivateLaser();
|
||||
StopIllumination();
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -94,7 +110,6 @@ namespace ActiveProtect.Models
|
||||
{
|
||||
Console.WriteLine($"激光目标指示器 {Id} 干扰解除,恢复工作");
|
||||
IsJammed = false;
|
||||
ActivateLaser();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -106,7 +121,7 @@ namespace ActiveProtect.Models
|
||||
IsActive = true;
|
||||
IsJammed = false;
|
||||
Console.WriteLine($"激光目标指示器 {Id} 已激活");
|
||||
IlluminateTarget(); // 立即开始照射目标
|
||||
UpdateIllumination();
|
||||
}
|
||||
|
||||
public void DeactivateLaser()
|
||||
@ -119,6 +134,14 @@ namespace ActiveProtect.Models
|
||||
}
|
||||
}
|
||||
|
||||
private void PublishIlluminationEvent()
|
||||
{
|
||||
PublishEvent(new LaserIlluminationEvent
|
||||
{
|
||||
TargetId = TargetId
|
||||
});
|
||||
}
|
||||
|
||||
private void PublishIlluminationStopEvent()
|
||||
{
|
||||
PublishEvent(new LaserIlluminationStopEvent
|
||||
@ -133,6 +156,7 @@ namespace ActiveProtect.Models
|
||||
$" 位置: {Position}\n" +
|
||||
$" 目标: {TargetId}\n" +
|
||||
$" 激活状态: {(IsActive ? "激活" : "未激活")}\n" +
|
||||
$" 照射状态: {(IsIlluminating ? "正在照射" : "未照射")}\n" +
|
||||
$" 干扰状态: {(IsJammed ? "被干扰" : "正常")}\n" +
|
||||
$" 最大照射范围: {MaxIlluminationRange}";
|
||||
}
|
||||
|
||||
@ -3,52 +3,90 @@ using ActiveProtect.SimulationEnvironment;
|
||||
|
||||
namespace ActiveProtect.Models
|
||||
{
|
||||
public class LaserJammer
|
||||
public class LaserJammer : SimulationElement
|
||||
{
|
||||
private readonly Tank tank;
|
||||
public bool IsJamming { get; private set; }
|
||||
public double JammingPower { get; private set; }
|
||||
private double jammingCooldown = 0;
|
||||
private const double MaxJammingCooldown = 5.0;
|
||||
private const double MaxJammingPower = 10000.0; // 降低最大干扰功率
|
||||
private const double InitialJammingPower = 4000.0; // 设置初始干扰功率
|
||||
private const double PowerIncreaseRate = 2000.0; // 每秒增加的功率
|
||||
private readonly double maxJammingCooldown;
|
||||
private readonly double maxJammingPower;
|
||||
private readonly double initialJammingPower;
|
||||
private readonly double powerIncreaseRate;
|
||||
public string MonitoredEntityId { get; private set; }
|
||||
|
||||
public LaserJammer(Tank tank)
|
||||
public LaserJammer(string id, Vector3D position, Orientation orientation, ISimulationManager simulationManager, string monitoredEntityId, LaserJammerConfig config)
|
||||
: base(id, position, orientation, simulationManager)
|
||||
{
|
||||
this.tank = tank;
|
||||
MonitoredEntityId = monitoredEntityId;
|
||||
IsJamming = false;
|
||||
JammingPower = 0;
|
||||
tank.SimulationManager.SubscribeToEvent<LaserIlluminationStopEvent>(OnLaserIlluminationStop);
|
||||
maxJammingCooldown = config.MaxJammingCooldown;
|
||||
maxJammingPower = config.MaxJammingPower;
|
||||
initialJammingPower = config.InitialJammingPower;
|
||||
powerIncreaseRate = config.PowerIncreaseRate;
|
||||
SimulationManager.SubscribeToEvent<LaserIlluminationEvent>(OnLaserIllumination);
|
||||
SimulationManager.SubscribeToEvent<LaserIlluminationStopEvent>(OnLaserIlluminationStop);
|
||||
}
|
||||
|
||||
public void Update(double deltaTime)
|
||||
public override void Update(double deltaTime)
|
||||
{
|
||||
if (!IsActive) return;
|
||||
|
||||
var tank = SimulationManager.GetEntityById(MonitoredEntityId) as Tank;
|
||||
if (tank != null)
|
||||
{
|
||||
Position = tank.Position;
|
||||
Orientation = tank.Orientation;
|
||||
}
|
||||
|
||||
if (IsJamming)
|
||||
{
|
||||
// 逐渐增加干扰功率
|
||||
JammingPower = Math.Min(JammingPower + PowerIncreaseRate * deltaTime, MaxJammingPower);
|
||||
JammingPower = Math.Min(JammingPower + powerIncreaseRate * deltaTime, maxJammingPower);
|
||||
|
||||
jammingCooldown += deltaTime;
|
||||
if (jammingCooldown >= MaxJammingCooldown)
|
||||
if (jammingCooldown >= maxJammingCooldown)
|
||||
{
|
||||
StopJamming();
|
||||
}
|
||||
else
|
||||
{
|
||||
// 发布干扰事件
|
||||
PublishEvent(new LaserJammingEvent
|
||||
{
|
||||
TargetId = MonitoredEntityId,
|
||||
JammingPower = JammingPower
|
||||
});
|
||||
}
|
||||
|
||||
Console.WriteLine($"坦克 {tank.Id} 的激光干扰器正在工作,当前功率: {JammingPower:F2}");
|
||||
Console.WriteLine($"激光干扰器 {Id} 正在工作,当前功率: {JammingPower:F2}");
|
||||
}
|
||||
else if (tank.LaserWarner.IsAlarming)
|
||||
}
|
||||
|
||||
private void OnLaserIllumination(LaserIlluminationEvent evt)
|
||||
{
|
||||
if (evt.TargetId == MonitoredEntityId)
|
||||
{
|
||||
StartJamming();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnLaserIlluminationStop(LaserIlluminationStopEvent evt)
|
||||
{
|
||||
if (evt.TargetId == MonitoredEntityId)
|
||||
{
|
||||
StopJamming();
|
||||
}
|
||||
}
|
||||
|
||||
private void StartJamming()
|
||||
{
|
||||
IsJamming = true;
|
||||
JammingPower = InitialJammingPower; // 从初始功率开始
|
||||
jammingCooldown = 0;
|
||||
Console.WriteLine($"坦克 {tank.Id} 的激光干扰器开始工作,初始功率: {JammingPower:F2}");
|
||||
if (!IsJamming)
|
||||
{
|
||||
IsJamming = true;
|
||||
JammingPower = initialJammingPower;
|
||||
jammingCooldown = 0;
|
||||
Console.WriteLine($"激光干扰器 {Id} 开始工作,初始功率: {JammingPower:F2}");
|
||||
}
|
||||
}
|
||||
|
||||
private void StopJamming()
|
||||
@ -58,17 +96,24 @@ namespace ActiveProtect.Models
|
||||
IsJamming = false;
|
||||
JammingPower = 0;
|
||||
jammingCooldown = 0;
|
||||
Console.WriteLine($"坦克 {tank.Id} 的激光干扰器停止工作");
|
||||
Console.WriteLine($"激光干扰器 {Id} 停止工作");
|
||||
}
|
||||
}
|
||||
|
||||
private void OnLaserIlluminationStop(LaserIlluminationStopEvent evt)
|
||||
public override string GetStatus()
|
||||
{
|
||||
if (evt.TargetId == tank.Id)
|
||||
{
|
||||
Console.WriteLine($"坦克 {tank.Id} 接收到激光照射停止事件,停止干扰");
|
||||
StopJamming();
|
||||
}
|
||||
return $"激光干扰器 {Id}:\n" +
|
||||
$" 监视实体: {MonitoredEntityId}\n" +
|
||||
$" 干扰状态: {(IsJamming ? "干扰中" : "未干扰")}\n" +
|
||||
$" 当前功率: {JammingPower:F2}/{maxJammingPower:F2}\n" +
|
||||
$" 冷却时间: {jammingCooldown:F2}/{maxJammingCooldown:F2}";
|
||||
}
|
||||
|
||||
protected override void Deactivate()
|
||||
{
|
||||
base.Deactivate();
|
||||
SimulationManager.UnsubscribeFromEvent<LaserIlluminationEvent>(OnLaserIllumination);
|
||||
SimulationManager.UnsubscribeFromEvent<LaserIlluminationStopEvent>(OnLaserIlluminationStop);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5,9 +5,7 @@ namespace ActiveProtect.Models
|
||||
{
|
||||
public class LaserSemiActiveGuidedMissile : Missile
|
||||
{
|
||||
public bool IsLaserDetected { get; private set; } = false;
|
||||
public bool IsLaserLocked { get; private set; } = false;
|
||||
private const double LaserLockDistance = 1000; // 1公里,单位:米
|
||||
private const double LaserLockDistance = 2000; // 1公里,单位:米
|
||||
|
||||
public LaserSemiActiveGuidedMissile(
|
||||
string id,
|
||||
@ -16,68 +14,67 @@ namespace ActiveProtect.Models
|
||||
: base(id, missileConfig, simulationManager)
|
||||
{
|
||||
Type = MissileType.SemiActiveLaserGuidance;
|
||||
simulationManager.SubscribeToEvent<LaserIlluminationEvent>(OnLaserIllumination);
|
||||
simulationManager.SubscribeToEvent<LaserIlluminationStopEvent>(OnLaserIlluminationStop);
|
||||
}
|
||||
|
||||
public override void Update(double deltaTime)
|
||||
{
|
||||
base.Update(deltaTime);
|
||||
UpdateLaserDetection();
|
||||
if (IsLaserDetected)
|
||||
UpdateGuidanceStatus();
|
||||
}
|
||||
|
||||
private void UpdateGuidanceStatus()
|
||||
{
|
||||
if (SimulationManager.GetEntityById(TargetId) is ILaserIlluminatable target)
|
||||
{
|
||||
UpdateLaserLock();
|
||||
IsGuidanceLost = false;
|
||||
bool isIlluminated = target.IsIlluminated;
|
||||
bool isWithinRange = DistanceToTarget <= LaserLockDistance;
|
||||
HasGuidance = isIlluminated && isWithinRange;
|
||||
|
||||
Console.WriteLine($"激光半主动制导导弹 {Id} 状态更新:");
|
||||
Console.WriteLine($" 目标 {TargetId} 是否被照射: {isIlluminated}");
|
||||
Console.WriteLine($" 距离目标: {DistanceToTarget:F2} m (最大锁定距离: {LaserLockDistance} m)");
|
||||
Console.WriteLine($" 是否在锁定范围内: {isWithinRange}");
|
||||
Console.WriteLine($" 引导状态: {(HasGuidance ? "有效" : "无效")}");
|
||||
}
|
||||
else
|
||||
{
|
||||
LoseGuidance();
|
||||
HasGuidance = false;
|
||||
Console.WriteLine($"激光半主动制导导弹 {Id} 无法找到目标 {TargetId}");
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateLaserDetection()
|
||||
private void OnLaserIllumination(LaserIlluminationEvent evt)
|
||||
{
|
||||
var target = SimulationManager.GetEntityById(TargetId) as ILaserIlluminatable;
|
||||
if (target != null)
|
||||
if (evt.TargetId == TargetId)
|
||||
{
|
||||
IsLaserDetected = target.IsIlluminated && DistanceToTarget <= LaserLockDistance;
|
||||
}
|
||||
else
|
||||
{
|
||||
IsLaserDetected = false;
|
||||
Console.WriteLine($"激光半主动制导导弹 {Id} 检测到目标 {TargetId} 被激光照射");
|
||||
UpdateGuidanceStatus();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateLaserLock()
|
||||
private void OnLaserIlluminationStop(LaserIlluminationStopEvent evt)
|
||||
{
|
||||
IsLaserLocked = IsLaserDetected;
|
||||
|
||||
if (IsLaserLocked)
|
||||
if (evt.TargetId == TargetId)
|
||||
{
|
||||
AdjustTrajectoryBasedOnLaserGuidance();
|
||||
}
|
||||
}
|
||||
|
||||
private void AdjustTrajectoryBasedOnLaserGuidance()
|
||||
{
|
||||
// 实现基于激光导引的轨迹调整
|
||||
// 这里可以添加更精确的导引逻辑
|
||||
}
|
||||
|
||||
protected override void LoseGuidance()
|
||||
{
|
||||
if (!IsLaserDetected)
|
||||
{
|
||||
base.LoseGuidance();
|
||||
IsLaserLocked = false;
|
||||
Console.WriteLine($"激光半主动制导导弹 {Id} 失去激光引导");
|
||||
Console.WriteLine($"激光半主动制导导弹 {Id} 检测到目标 {TargetId} 激光照射停止");
|
||||
UpdateGuidanceStatus();
|
||||
}
|
||||
}
|
||||
|
||||
public override string GetStatus()
|
||||
{
|
||||
string baseStatus = base.GetStatus().Replace("导弹", "激光半主动制导导弹");
|
||||
string additionalStatus = $"\n 激光检测: {(IsLaserDetected ? "是" : "否")}" +
|
||||
$"\n 激光锁定: {(IsLaserLocked ? "是" : "否")}";
|
||||
string additionalStatus = $"\n 激光引导: {(HasGuidance ? "有效" : "无效")}";
|
||||
return baseStatus + additionalStatus;
|
||||
}
|
||||
|
||||
protected override void Deactivate()
|
||||
{
|
||||
base.Deactivate();
|
||||
SimulationManager.UnsubscribeFromEvent<LaserIlluminationEvent>(OnLaserIllumination);
|
||||
SimulationManager.UnsubscribeFromEvent<LaserIlluminationStopEvent>(OnLaserIlluminationStop);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3,23 +3,34 @@ using System;
|
||||
|
||||
namespace ActiveProtect.Models
|
||||
{
|
||||
public class LaserWarner
|
||||
public class LaserWarner : SimulationElement
|
||||
{
|
||||
private readonly Tank tank;
|
||||
public bool IsAlarming { get; private set; }
|
||||
private double alarmDuration = 5.0; // 警报持续5秒
|
||||
private readonly double alarmDuration;
|
||||
private double alarmTimer = 0;
|
||||
public string MonitoredEntityId { get; private set; }
|
||||
|
||||
public LaserWarner(Tank tank)
|
||||
public LaserWarner(string id, Vector3D position, Orientation orientation, ISimulationManager simulationManager, string monitoredEntityId, LaserWarnerConfig config)
|
||||
: base(id, position, orientation, simulationManager)
|
||||
{
|
||||
this.tank = tank;
|
||||
MonitoredEntityId = monitoredEntityId;
|
||||
IsAlarming = false;
|
||||
tank.SimulationManager.SubscribeToEvent<LaserIlluminationEvent>(OnLaserIllumination);
|
||||
tank.SimulationManager.SubscribeToEvent<LaserIlluminationStopEvent>(OnLaserIlluminationStop);
|
||||
alarmDuration = config.AlarmDuration;
|
||||
SimulationManager.SubscribeToEvent<LaserIlluminationEvent>(OnLaserIllumination);
|
||||
SimulationManager.SubscribeToEvent<LaserIlluminationStopEvent>(OnLaserIlluminationStop);
|
||||
}
|
||||
|
||||
public void Update(double deltaTime)
|
||||
public override void Update(double deltaTime)
|
||||
{
|
||||
if (!IsActive) return;
|
||||
|
||||
var tank = SimulationManager.GetEntityById(MonitoredEntityId) as Tank;
|
||||
if (tank != null)
|
||||
{
|
||||
Position = tank.Position;
|
||||
Orientation = tank.Orientation;
|
||||
}
|
||||
|
||||
if (IsAlarming)
|
||||
{
|
||||
alarmTimer += deltaTime;
|
||||
@ -32,7 +43,7 @@ namespace ActiveProtect.Models
|
||||
|
||||
private void OnLaserIllumination(LaserIlluminationEvent evt)
|
||||
{
|
||||
if (evt.TargetId == tank.Id)
|
||||
if (evt.TargetId == MonitoredEntityId)
|
||||
{
|
||||
TriggerAlarm();
|
||||
}
|
||||
@ -40,7 +51,7 @@ namespace ActiveProtect.Models
|
||||
|
||||
private void OnLaserIlluminationStop(LaserIlluminationStopEvent evt)
|
||||
{
|
||||
if (evt.TargetId == tank.Id)
|
||||
if (evt.TargetId == MonitoredEntityId)
|
||||
{
|
||||
StopAlarm();
|
||||
}
|
||||
@ -52,7 +63,7 @@ namespace ActiveProtect.Models
|
||||
{
|
||||
IsAlarming = true;
|
||||
alarmTimer = 0;
|
||||
Console.WriteLine($"坦克 {tank.Id} 的激光告警器发出警报!");
|
||||
Console.WriteLine($"激光告警器 {Id} 发出警报!");
|
||||
}
|
||||
}
|
||||
|
||||
@ -62,8 +73,23 @@ namespace ActiveProtect.Models
|
||||
{
|
||||
IsAlarming = false;
|
||||
alarmTimer = 0;
|
||||
Console.WriteLine($"坦克 {tank.Id} 的激光告警器停止警报");
|
||||
Console.WriteLine($"激光告警器 {Id} 停止警报");
|
||||
}
|
||||
}
|
||||
|
||||
public override string GetStatus()
|
||||
{
|
||||
return $"激光告警器 {Id}:\n" +
|
||||
$" 监视实体: {MonitoredEntityId}\n" +
|
||||
$" 警报状态: {(IsAlarming ? "警报中" : "正常")}\n" +
|
||||
$" 警报持续时间: {(IsAlarming ? alarmTimer : 0):F2}/{alarmDuration:F2}";
|
||||
}
|
||||
|
||||
protected override void Deactivate()
|
||||
{
|
||||
base.Deactivate();
|
||||
SimulationManager.UnsubscribeFromEvent<LaserIlluminationEvent>(OnLaserIllumination);
|
||||
SimulationManager.UnsubscribeFromEvent<LaserIlluminationStopEvent>(OnLaserIlluminationStop);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -39,7 +39,6 @@ namespace ActiveProtect.Models
|
||||
public MissileDistanceParams DistanceParams { get; protected set; }
|
||||
public FlightStageConfig StageConfig { get; protected set; }
|
||||
public FlightStage CurrentStage { get; protected set; }
|
||||
public bool IsActive { get; protected set; }
|
||||
|
||||
protected Vector3D Velocity;
|
||||
private Vector3D LastTargetPosition;
|
||||
@ -53,7 +52,7 @@ namespace ActiveProtect.Models
|
||||
|
||||
public double ProportionalNavigationCoefficient { get; set; }
|
||||
|
||||
public bool IsGuidanceLost { get; protected set; } = false;
|
||||
public bool HasGuidance { get; protected set; } = true;
|
||||
protected double LostGuidanceTime { get; set; } = 0;
|
||||
protected const double MaxLostGuidanceTime = 1.0; // 1秒后自毁
|
||||
|
||||
@ -90,15 +89,19 @@ namespace ActiveProtect.Models
|
||||
|
||||
LastTargetPosition = Position; // 初始化 LastTargetPosition
|
||||
|
||||
// 订阅相关事件
|
||||
simulationManager.SubscribeToEvent<LaserIlluminationEvent>(OnLaserIllumination);
|
||||
simulationManager.SubscribeToEvent<LaserIlluminationStopEvent>(OnLaserIlluminationStop);
|
||||
}
|
||||
|
||||
public override void Update(double deltaTime)
|
||||
{
|
||||
if (!IsActive) return;
|
||||
|
||||
// 首先检查是否应该自毁
|
||||
if (ShouldSelfDestruct())
|
||||
{
|
||||
SelfDestruct();
|
||||
return;
|
||||
}
|
||||
|
||||
// 更新发动机燃烧时间
|
||||
UpdateEngineBurnTime(deltaTime);
|
||||
|
||||
@ -125,33 +128,24 @@ namespace ActiveProtect.Models
|
||||
Orientation = Orientation.FromVector(Velocity);
|
||||
FlightTime += deltaTime;
|
||||
FlightDistance += Speed * deltaTime;
|
||||
DistanceToTarget = Vector3D.Distance(Position, SimulationManager.GetEntityById(TargetId).Position);
|
||||
|
||||
UpdateDistanceToTarget(Vector3D.Distance(Position, SimulationManager.GetEntityById(TargetId).Position));
|
||||
|
||||
// 首先检查是否命中目标
|
||||
// 检查是否命中目标
|
||||
if (CheckHit())
|
||||
{
|
||||
Explode();
|
||||
return;
|
||||
}
|
||||
|
||||
// 然后检查是否应该自毁
|
||||
if (ShouldSelfDestruct())
|
||||
{
|
||||
SelfDestruct();
|
||||
return;
|
||||
}
|
||||
|
||||
// 更新飞行阶段
|
||||
UpdateFlightStage();
|
||||
|
||||
if (IsGuidanceLost)
|
||||
if (!HasGuidance)
|
||||
{
|
||||
HandleLostGuidance(deltaTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 重置失去引导的时间
|
||||
LostGuidanceTime = 0;
|
||||
}
|
||||
|
||||
@ -169,7 +163,22 @@ namespace ActiveProtect.Models
|
||||
|
||||
private bool ShouldSelfDestruct()
|
||||
{
|
||||
return FlightTime >= MaxFlightTime || FlightDistance >= MaxFlightDistance || Position.Y <= 0;
|
||||
if (FlightTime >= MaxFlightTime)
|
||||
{
|
||||
Console.WriteLine($"导弹 {Id} 超出最大飞行时间 ({FlightTime:F2}/{MaxFlightTime:F2}),准备自毁");
|
||||
return true;
|
||||
}
|
||||
if (FlightDistance >= MaxFlightDistance)
|
||||
{
|
||||
Console.WriteLine($"导弹 {Id} 超出最大飞行距离 ({FlightDistance:F2}/{MaxFlightDistance:F2}),准备自毁");
|
||||
return true;
|
||||
}
|
||||
if (Position.Y <= 0)
|
||||
{
|
||||
Console.WriteLine($"导弹 {Id} 高度小于等于0 ({Position.Y:F2}),准备自毁");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void UpdateEngineBurnTime(double deltaTime)
|
||||
@ -248,27 +257,25 @@ namespace ActiveProtect.Models
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateDistanceToTarget(double distance)
|
||||
{
|
||||
DistanceToTarget = distance;
|
||||
}
|
||||
|
||||
public void Explode()
|
||||
{
|
||||
IsActive = false;
|
||||
Deactivate();
|
||||
SimulationManager.HandleTargetHit(TargetId, Id);
|
||||
Console.WriteLine($"导弹 {Id} 在 {Position} 爆炸,命中目标!");
|
||||
}
|
||||
|
||||
public void SelfDestruct()
|
||||
{
|
||||
IsActive = false;
|
||||
string reason = FlightTime >= MaxFlightTime ? "超出最大飞行时间" :
|
||||
FlightDistance >= MaxFlightDistance ? "超出最大飞行距" :
|
||||
Position.Y <= 0 ? "高度小于等于0" :
|
||||
IsGuidanceLost ? "失去引导" : "未知原因";
|
||||
|
||||
Console.WriteLine($"导弹 {Id} 自毁。原因: {reason}");
|
||||
if (IsActive)
|
||||
{
|
||||
string reason = FlightTime >= MaxFlightTime ? "超出最大飞行时间" :
|
||||
FlightDistance >= MaxFlightDistance ? "超出最大飞行距离" :
|
||||
Position.Y <= 0 ? "高度小于等于0" :
|
||||
!HasGuidance ? "失去引导" : "未知原因";
|
||||
|
||||
Console.WriteLine($"导弹 {Id} 自毁。原因: {reason}");
|
||||
Deactivate();
|
||||
}
|
||||
}
|
||||
|
||||
public override string GetStatus()
|
||||
@ -281,7 +288,7 @@ namespace ActiveProtect.Models
|
||||
$" 飞行距离: {FlightDistance:F2}/{MaxFlightDistance:F2}\n" +
|
||||
$" 距离目标: {DistanceToTarget:F2}\n" +
|
||||
$" 发动机工作时间: {EngineBurnTime:F2}/{MaxEngineBurnTime:F2}\n" +
|
||||
$" 失去引导: {(IsGuidanceLost ? "是" : "否")}\n" +
|
||||
$" 有引导: {(HasGuidance ? "是" : "否")}\n" +
|
||||
$" 失去引导时间: {LostGuidanceTime:F2}/{MaxLostGuidanceTime:F2}";
|
||||
}
|
||||
|
||||
@ -291,15 +298,6 @@ namespace ActiveProtect.Models
|
||||
Console.WriteLine($"导弹 {Id} 的比例导引系数已更新为 {newCoefficient}");
|
||||
}
|
||||
|
||||
protected virtual void LoseGuidance()
|
||||
{
|
||||
if (!IsGuidanceLost)
|
||||
{
|
||||
Console.WriteLine($"导弹 {Id} 失去引导");
|
||||
IsGuidanceLost = true;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void HandleLostGuidance(double deltaTime)
|
||||
{
|
||||
LostGuidanceTime += deltaTime;
|
||||
@ -310,33 +308,6 @@ namespace ActiveProtect.Models
|
||||
}
|
||||
}
|
||||
|
||||
private void OnLaserIllumination(LaserIlluminationEvent evt)
|
||||
{
|
||||
if (evt.TargetId == TargetId)
|
||||
{
|
||||
Console.WriteLine($"导弹 {Id} 检测到目标 {TargetId} 被激光照射");
|
||||
RegainGuidance();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnLaserIlluminationStop(LaserIlluminationStopEvent evt)
|
||||
{
|
||||
if (evt.TargetId == TargetId)
|
||||
{
|
||||
Console.WriteLine($"导弹 {Id} 检测到目标 {TargetId} 激光照射停止");
|
||||
LoseGuidance();
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void RegainGuidance()
|
||||
{
|
||||
if (IsGuidanceLost)
|
||||
{
|
||||
Console.WriteLine($"导弹 {Id} 重新获得引导");
|
||||
IsGuidanceLost = false;
|
||||
LostGuidanceTime = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -6,13 +6,10 @@ namespace ActiveProtect.Models
|
||||
public class Tank : SimulationElement, ILaserIlluminatable
|
||||
{
|
||||
public double Speed { get; set; } = 0;
|
||||
public bool IsActive { get; private set; } = true;
|
||||
public double MaxSpeed { get; private set; }
|
||||
public double MaxArmor { get; private set; }
|
||||
public double CurrentArmor { get; private set; }
|
||||
public bool IsIlluminated { get; private set; } = false;
|
||||
public LaserWarner LaserWarner { get; private set; }
|
||||
public LaserJammer LaserJammer { get; private set; }
|
||||
|
||||
public Tank(string id, TankConfig tankConfig, ISimulationManager simulationManager)
|
||||
: base(id, tankConfig.InitialPosition, tankConfig.InitialOrientation, simulationManager)
|
||||
@ -21,10 +18,6 @@ namespace ActiveProtect.Models
|
||||
MaxSpeed = tankConfig.MaxSpeed;
|
||||
MaxArmor = tankConfig.MaxArmor;
|
||||
CurrentArmor = tankConfig.MaxArmor;
|
||||
LaserWarner = new LaserWarner(this);
|
||||
LaserJammer = new LaserJammer(this);
|
||||
|
||||
// 移除事件订阅,因为现在由LaserWarner直接处理
|
||||
}
|
||||
|
||||
public override void Update(double deltaTime)
|
||||
@ -32,18 +25,7 @@ namespace ActiveProtect.Models
|
||||
if (!IsActive) return;
|
||||
|
||||
UpdatePosition(deltaTime);
|
||||
LaserWarner.Update(deltaTime);
|
||||
LaserJammer.Update(deltaTime);
|
||||
|
||||
// 如果激光干扰器正在工作,发布LaserJammingEvent
|
||||
if (LaserJammer.IsJamming)
|
||||
{
|
||||
PublishEvent(new LaserJammingEvent
|
||||
{
|
||||
TargetId = Id,
|
||||
JammingPower = LaserJammer.JammingPower
|
||||
});
|
||||
}
|
||||
// 移除发布坦克位置更新事件的代码
|
||||
}
|
||||
|
||||
private void UpdatePosition(double deltaTime)
|
||||
@ -63,23 +45,28 @@ namespace ActiveProtect.Models
|
||||
CurrentArmor = Math.Max(0, CurrentArmor - damage);
|
||||
if (CurrentArmor <= 0)
|
||||
{
|
||||
IsActive = false;
|
||||
PublishEvent(new EntityDestroyedEvent { DestroyedEntityId = Id });
|
||||
Deactivate();
|
||||
}
|
||||
}
|
||||
|
||||
public void Illuminate()
|
||||
{
|
||||
IsIlluminated = true;
|
||||
if (!IsIlluminated)
|
||||
{
|
||||
IsIlluminated = true;
|
||||
Console.WriteLine($"坦克 {Id} 被激光照射");
|
||||
}
|
||||
}
|
||||
|
||||
public void StopIllumination()
|
||||
{
|
||||
IsIlluminated = false;
|
||||
if (IsIlluminated)
|
||||
{
|
||||
IsIlluminated = false;
|
||||
Console.WriteLine($"坦克 {Id} 激光照射停止");
|
||||
}
|
||||
}
|
||||
|
||||
// 移除OnLaserIllumination和OnLaserIlluminationStop方法,因为现在由LaserWarner直接处理
|
||||
|
||||
public override string GetStatus()
|
||||
{
|
||||
return $"坦克 {Id}:\n" +
|
||||
@ -87,9 +74,7 @@ namespace ActiveProtect.Models
|
||||
$" 速度: {Speed:F2}/{MaxSpeed:F2}\n" +
|
||||
$" 装甲: {CurrentArmor:F2}/{MaxArmor:F2}\n" +
|
||||
$" 状态: {(IsActive ? "活动" : "已销毁")}\n" +
|
||||
$" 激光照射: {(IsIlluminated ? "是" : "否")}\n" +
|
||||
$" 激光报警: {(LaserWarner.IsAlarming ? "警报中" : "正常")}\n" +
|
||||
$" 激光干扰: {(LaserJammer.IsJamming ? $"干扰中 (功率: {LaserJammer.JammingPower:F2})" : "未干扰")}";
|
||||
$" 激光照射: {(IsIlluminated ? "是" : "否")}\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
27
Program.cs
27
Program.cs
@ -19,9 +19,22 @@ namespace ActiveProtect
|
||||
InitialOrientation = new Orientation(0, 0, 0),
|
||||
InitialSpeed = 0,
|
||||
MaxSpeed = 20,
|
||||
MaxArmor = 100
|
||||
MaxArmor = 100,
|
||||
HasLaserWarner = true,
|
||||
HasLaserJammer = true
|
||||
}
|
||||
],
|
||||
LaserWarnerConfig = new LaserWarnerConfig
|
||||
{
|
||||
AlarmDuration = 5.0
|
||||
},
|
||||
LaserJammerConfig = new LaserJammerConfig
|
||||
{
|
||||
MaxJammingCooldown = 5.0,
|
||||
MaxJammingPower = 10000.0,
|
||||
InitialJammingPower = 4000.0,
|
||||
PowerIncreaseRate = 2000.0
|
||||
},
|
||||
MissileConfigs =
|
||||
[
|
||||
// 标准导弹配置
|
||||
@ -31,7 +44,7 @@ namespace ActiveProtect
|
||||
InitialSpeed = 10,
|
||||
MaxSpeed = 400,
|
||||
TargetIndex = 0,
|
||||
MaxFlightTime = 0,
|
||||
MaxFlightTime = 0.5,
|
||||
MaxFlightDistance = 5000,
|
||||
ThrustAcceleration = 80,
|
||||
MaxEngineBurnTime = 5,
|
||||
@ -48,7 +61,7 @@ namespace ActiveProtect
|
||||
InitialSpeed = 700,
|
||||
MaxSpeed = 800,
|
||||
TargetIndex = 0,
|
||||
MaxFlightTime = 0,
|
||||
MaxFlightTime = 0.5,
|
||||
MaxFlightDistance = 5000,
|
||||
ThrustAcceleration = 50,
|
||||
MaxEngineBurnTime = 5,
|
||||
@ -65,7 +78,7 @@ namespace ActiveProtect
|
||||
InitialSpeed = 10,
|
||||
MaxSpeed = 300,
|
||||
TargetIndex = 0,
|
||||
MaxFlightTime = 0,
|
||||
MaxFlightTime = 0.5,
|
||||
MaxFlightDistance = 3000,
|
||||
ThrustAcceleration = 50,
|
||||
MaxEngineBurnTime = 5,
|
||||
@ -82,7 +95,7 @@ namespace ActiveProtect
|
||||
InitialSpeed = 700,
|
||||
MaxSpeed = 800,
|
||||
TargetIndex = 0,
|
||||
MaxFlightTime = 20,
|
||||
MaxFlightTime = 5,
|
||||
MaxFlightDistance = 4500,
|
||||
ThrustAcceleration = 50,
|
||||
MaxEngineBurnTime = 5,
|
||||
@ -98,7 +111,6 @@ namespace ActiveProtect
|
||||
new LaserDesignatorConfig
|
||||
{
|
||||
InitialPosition = new Vector3D(500, 150, 100),
|
||||
TargetId = "Tank_1",
|
||||
MaxIlluminationRange = 1000
|
||||
}
|
||||
],
|
||||
@ -109,7 +121,7 @@ namespace ActiveProtect
|
||||
var simulationManager = new SimulationManager(config);
|
||||
|
||||
// 运行仿真
|
||||
int maxIterations = 1000; // 增加最大迭代次数
|
||||
int maxIterations = 1000;
|
||||
int iteration = 0;
|
||||
while (!simulationManager.IsSimulationEnded && iteration < maxIterations)
|
||||
{
|
||||
@ -121,6 +133,5 @@ namespace ActiveProtect
|
||||
|
||||
Console.WriteLine("仿真结束");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -7,6 +7,8 @@ namespace ActiveProtect.SimulationEnvironment
|
||||
public List<TankConfig> TankConfigs { get; set; }
|
||||
public List<MissileConfig> MissileConfigs { get; set; }
|
||||
public List<LaserDesignatorConfig> LaserDesignatorConfigs { get; set; }
|
||||
public LaserWarnerConfig LaserWarnerConfig { get; set; }
|
||||
public LaserJammerConfig LaserJammerConfig { get; set; }
|
||||
public double SimulationTimeStep { get; set; }
|
||||
|
||||
public SimulationConfig()
|
||||
@ -14,6 +16,8 @@ namespace ActiveProtect.SimulationEnvironment
|
||||
TankConfigs = [];
|
||||
MissileConfigs = [];
|
||||
LaserDesignatorConfigs = [];
|
||||
LaserWarnerConfig = new LaserWarnerConfig();
|
||||
LaserJammerConfig = new LaserJammerConfig();
|
||||
SimulationTimeStep = 0.1; // 默认时间步长为0.1秒
|
||||
}
|
||||
}
|
||||
@ -26,6 +30,9 @@ namespace ActiveProtect.SimulationEnvironment
|
||||
public double MaxSpeed { get; set; }
|
||||
public double MaxArmor { get; set; }
|
||||
|
||||
public bool HasLaserWarner { get; set; }
|
||||
public bool HasLaserJammer { get; set; }
|
||||
|
||||
public TankConfig()
|
||||
{
|
||||
InitialPosition = new Vector3D(0, 0, 0);
|
||||
@ -53,7 +60,7 @@ namespace ActiveProtect.SimulationEnvironment
|
||||
|
||||
public MissileConfig()
|
||||
{
|
||||
InitialPosition = new Vector3D(0, 0, 0); // 初始位<EFBFBD><EFBFBD>
|
||||
InitialPosition = new Vector3D(0, 0, 0); // 初始位
|
||||
InitialOrientation = new Orientation(0, 0, 0); // 初始方向
|
||||
InitialSpeed = 0; // 初始速度
|
||||
MaxSpeed = 0; // 最大速度
|
||||
@ -73,12 +80,10 @@ namespace ActiveProtect.SimulationEnvironment
|
||||
public class LaserDesignatorConfig
|
||||
{
|
||||
public Vector3D InitialPosition { get; set; }
|
||||
public string TargetId { get; set; }
|
||||
public double MaxIlluminationRange { get; set; }
|
||||
public LaserDesignatorConfig()
|
||||
{
|
||||
InitialPosition = new Vector3D(0, 0, 0);
|
||||
TargetId = "";
|
||||
MaxIlluminationRange = 1000;
|
||||
}
|
||||
}
|
||||
@ -125,4 +130,31 @@ namespace ActiveProtect.SimulationEnvironment
|
||||
/// </summary>
|
||||
public static FlightStageConfig LaserSemiActiveGuidedMissile => new(enableAcceleration: false);
|
||||
}
|
||||
}
|
||||
|
||||
public class LaserWarnerConfig
|
||||
{
|
||||
public double AlarmDuration { get; set; }
|
||||
|
||||
public LaserWarnerConfig()
|
||||
{
|
||||
AlarmDuration = 5.0; // 默认警报持续5秒
|
||||
}
|
||||
}
|
||||
|
||||
public class LaserJammerConfig
|
||||
{
|
||||
public double MaxJammingCooldown { get; set; }
|
||||
public double MaxJammingPower { get; set; }
|
||||
public double InitialJammingPower { get; set; }
|
||||
public double PowerIncreaseRate { get; set; }
|
||||
|
||||
public LaserJammerConfig()
|
||||
{
|
||||
MaxJammingCooldown = 5.0;
|
||||
MaxJammingPower = 10000.0;
|
||||
InitialJammingPower = 4000.0;
|
||||
PowerIncreaseRate = 2000.0; // 每秒增加的功率
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -8,12 +8,13 @@ namespace ActiveProtect.SimulationEnvironment
|
||||
public Vector3D Position { get; set; } = position;
|
||||
public Orientation Orientation { get; set; } = orientation;
|
||||
public ISimulationManager SimulationManager { get; set; } = simulationManager;
|
||||
public bool IsActive { get; protected set; } = true;
|
||||
|
||||
public abstract void Update(double deltaTime);
|
||||
|
||||
public virtual string GetStatus()
|
||||
{
|
||||
return $"{GetType().Name} {Id} at {Position}, Orientation: {Orientation}";
|
||||
return $"{GetType().Name} {Id} at {Position}, Orientation: {Orientation}, Active: {IsActive}";
|
||||
}
|
||||
|
||||
protected void PublishEvent(SimulationEvent evt)
|
||||
@ -22,5 +23,17 @@ namespace ActiveProtect.SimulationEnvironment
|
||||
evt.Timestamp = SimulationManager.CurrentTime;
|
||||
SimulationManager.PublishEvent(evt);
|
||||
}
|
||||
|
||||
protected virtual void Activate()
|
||||
{
|
||||
IsActive = true;
|
||||
PublishEvent(new EntityActivatedEvent { ActivatedEntityId = Id });
|
||||
}
|
||||
|
||||
protected virtual void Deactivate()
|
||||
{
|
||||
IsActive = false;
|
||||
PublishEvent(new EntityDeactivatedEvent { DeactivatedEntityId = Id });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -31,4 +31,14 @@ namespace ActiveProtect.SimulationEnvironment
|
||||
{
|
||||
public string? TargetId { get; set; }
|
||||
}
|
||||
|
||||
public class EntityActivatedEvent : SimulationEvent
|
||||
{
|
||||
public string? ActivatedEntityId { get; set; }
|
||||
}
|
||||
|
||||
public class EntityDeactivatedEvent : SimulationEvent
|
||||
{
|
||||
public string? DeactivatedEntityId { get; set; }
|
||||
}
|
||||
}
|
||||
@ -9,12 +9,14 @@ namespace ActiveProtect.SimulationEnvironment
|
||||
{
|
||||
double CurrentTime { get; }
|
||||
|
||||
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;
|
||||
void UnsubscribeAllEvents(SimulationElement element);
|
||||
}
|
||||
|
||||
public class SimulationManager : ISimulationManager
|
||||
@ -24,6 +26,7 @@ namespace ActiveProtect.SimulationEnvironment
|
||||
public bool IsSimulationEnded { get; private set; }
|
||||
private readonly SimulationConfig config;
|
||||
private Dictionary<Type, List<Delegate>> eventHandlers = new Dictionary<Type, List<Delegate>>();
|
||||
private Dictionary<SimulationElement, List<(Type, Delegate)>> elementSubscriptions = new Dictionary<SimulationElement, List<(Type, Delegate)>>();
|
||||
|
||||
public SimulationManager(SimulationConfig config)
|
||||
{
|
||||
@ -36,17 +39,54 @@ namespace ActiveProtect.SimulationEnvironment
|
||||
|
||||
private void InitializeSimulation()
|
||||
{
|
||||
// 创建坦克(保持不变)
|
||||
// 创建坦克
|
||||
for (int i = 0; i < config.TankConfigs.Count; i++)
|
||||
{
|
||||
var tankConfig = config.TankConfigs[i];
|
||||
Elements.Add(new Tank($"Tank_{i + 1}", tankConfig, this));
|
||||
var tank = new Tank($"Tank_{i + 1}", tankConfig, this);
|
||||
Elements.Add(tank);
|
||||
|
||||
// 为坦克创建激光告警器
|
||||
if (tankConfig.HasLaserWarner)
|
||||
{
|
||||
var laserWarner = new LaserWarner(
|
||||
$"LaserWarner_{tank.Id}",
|
||||
tank.Position,
|
||||
tank.Orientation,
|
||||
this,
|
||||
tank.Id,
|
||||
config.LaserWarnerConfig
|
||||
);
|
||||
Elements.Add(laserWarner);
|
||||
}
|
||||
|
||||
// 为坦克创建激光干扰机
|
||||
if (tankConfig.HasLaserJammer)
|
||||
{
|
||||
var laserJammer = new LaserJammer(
|
||||
$"LaserJammer_{tank.Id}",
|
||||
tank.Position,
|
||||
tank.Orientation,
|
||||
this,
|
||||
tank.Id,
|
||||
config.LaserJammerConfig
|
||||
);
|
||||
Elements.Add(laserJammer);
|
||||
}
|
||||
}
|
||||
|
||||
// 创建导弹(修改这部分)
|
||||
for (int i = 0; i < config.MissileConfigs.Count; i++)
|
||||
{
|
||||
var missileConfig = config.MissileConfigs[i];
|
||||
|
||||
// 确保 MaxFlightTime 设置合理
|
||||
if (missileConfig.MaxFlightTime <= 0)
|
||||
{
|
||||
missileConfig.MaxFlightTime = 300; // 设置一个默认值,比如 300 秒
|
||||
Console.WriteLine($"警告:导弹配置 {i} 的 MaxFlightTime 无效,已设置为默认值 300 秒");
|
||||
}
|
||||
|
||||
Missile missile = missileConfig.Type switch
|
||||
{
|
||||
MissileType.SemiActiveLaserGuidance => new LaserSemiActiveGuidedMissile(
|
||||
@ -67,7 +107,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}", laserDesignatorConfig, this);
|
||||
var laserDesignator = new LaserDesignator($"LD_{i + 1}", "Tank_1", laserDesignatorConfig, this);
|
||||
Elements.Add(laserDesignator);
|
||||
laserDesignator.ActivateLaser(); // 激活激光目标指示器
|
||||
}
|
||||
@ -93,6 +133,17 @@ namespace ActiveProtect.SimulationEnvironment
|
||||
eventHandlers[eventType] = new List<Delegate>();
|
||||
}
|
||||
eventHandlers[eventType].Add(handler);
|
||||
|
||||
// 记录订阅关系
|
||||
var element = Elements.FirstOrDefault(e => e.GetType().GetMethods().Any(m => m.Name == handler.Method.Name));
|
||||
if (element != null)
|
||||
{
|
||||
if (!elementSubscriptions.ContainsKey(element))
|
||||
{
|
||||
elementSubscriptions[element] = new List<(Type, Delegate)>();
|
||||
}
|
||||
elementSubscriptions[element].Add((eventType, handler));
|
||||
}
|
||||
}
|
||||
|
||||
public void UnsubscribeFromEvent<T>(Action<T> handler) where T : SimulationEvent
|
||||
@ -102,6 +153,28 @@ namespace ActiveProtect.SimulationEnvironment
|
||||
{
|
||||
eventHandlers[eventType].Remove(handler);
|
||||
}
|
||||
|
||||
// 移除订阅关系记录
|
||||
var element = Elements.FirstOrDefault(e => e.GetType().GetMethods().Any(m => m.Name == handler.Method.Name));
|
||||
if (element != null && elementSubscriptions.ContainsKey(element))
|
||||
{
|
||||
elementSubscriptions[element].RemoveAll(s => Delegate.Equals(s.Item2, handler));
|
||||
}
|
||||
}
|
||||
|
||||
public void UnsubscribeAllEvents(SimulationElement element)
|
||||
{
|
||||
if (elementSubscriptions.ContainsKey(element))
|
||||
{
|
||||
foreach (var subscription in elementSubscriptions[element])
|
||||
{
|
||||
if (eventHandlers.ContainsKey(subscription.Item1))
|
||||
{
|
||||
eventHandlers[subscription.Item1].Remove(subscription.Item2);
|
||||
}
|
||||
}
|
||||
elementSubscriptions.Remove(element);
|
||||
}
|
||||
}
|
||||
|
||||
public void Update()
|
||||
@ -112,14 +185,21 @@ namespace ActiveProtect.SimulationEnvironment
|
||||
|
||||
foreach (var element in Elements.ToList())
|
||||
{
|
||||
element.Update(config.SimulationTimeStep);
|
||||
if (element.IsActive)
|
||||
{
|
||||
element.Update(config.SimulationTimeStep);
|
||||
}
|
||||
else
|
||||
{
|
||||
UnsubscribeAllEvents(element);
|
||||
}
|
||||
}
|
||||
|
||||
// 移除不活跃的元素
|
||||
Elements.RemoveAll(e => (e is Tank tank && !tank.IsActive) || (e is Missile missile && !missile.IsActive));
|
||||
Elements.RemoveAll(e => !e.IsActive);
|
||||
|
||||
// 检查是否所有导弹都结束飞行
|
||||
if (!Elements.Any(e => e is Missile))
|
||||
if (!Elements.Any(e => e is Missile && e.IsActive))
|
||||
{
|
||||
EndSimulation();
|
||||
}
|
||||
@ -158,19 +238,11 @@ namespace ActiveProtect.SimulationEnvironment
|
||||
// 对坦克造成伤害
|
||||
tank.TakeDamage(damage, true);
|
||||
|
||||
// 移除已爆炸的导弹
|
||||
RemoveEntity(missileId);
|
||||
|
||||
// 记录击中事件
|
||||
LogHitEvent(targetId, missileId, damage);
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveEntity(string missileId)
|
||||
{
|
||||
Elements.Remove(GetEntityById(missileId));
|
||||
}
|
||||
|
||||
private double CalculateMissileDamage(Missile missile)
|
||||
{
|
||||
// 这里可以根据导弹类型、速度等因素计算伤害
|
||||
@ -178,9 +250,14 @@ namespace ActiveProtect.SimulationEnvironment
|
||||
return 100;
|
||||
}
|
||||
|
||||
private void LogHitEvent(string targetId, string missileId, double damage)
|
||||
private static void LogHitEvent(string targetId, string missileId, double damage)
|
||||
{
|
||||
Console.WriteLine($"目标 {targetId} 被导弹 {missileId} 击中,造成 {damage} 点伤害");
|
||||
}
|
||||
|
||||
public void AddElement(SimulationElement element)
|
||||
{
|
||||
Elements.Add(element);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user