增加激光报警器和激光干扰机, 仿真过程改为事件驱动机制
This commit is contained in:
parent
e94e94e031
commit
d9975acd3c
121
Design.md
Normal file
121
Design.md
Normal file
@ -0,0 +1,121 @@
|
||||
# 导弹仿真系统设计文档
|
||||
|
||||
## 系统架构设计思路
|
||||
|
||||
在处理导弹、坦克、告警设备、干扰设备等复杂交互关系时,我们采用了以下几种程序架构和设计模式的组合:
|
||||
|
||||
### 1. 事件驱动架构(Event-Driven Architecture)
|
||||
|
||||
事件驱动架构非常适合处理复杂的交互关系。每个实体(如导弹、坦克等)可以发布事件,其他实体可以订阅这些事件并作出反应。
|
||||
|
||||
``csharp
|
||||
public class EventManager
|
||||
{
|
||||
private Dictionary<string, List<Action<object>>> eventSubscribers = new Dictionary<string, List<Action<object>>>();
|
||||
public void Subscribe(string eventName, Action<object> listener) { ... }
|
||||
public void Publish(string eventName, object eventData) { ... }
|
||||
}
|
||||
``
|
||||
|
||||
### 2. 组件系统(Component System)
|
||||
|
||||
将每个实体分解为多个组件,每个组件负责特定的功能。这样可以更灵活地组合不同的功能。
|
||||
|
||||
``csharp
|
||||
public class Entity
|
||||
{
|
||||
public PositionComponent Position { get; set; }
|
||||
public VelocityComponent Velocity { get; set; }
|
||||
public HealthComponent Health { get; set; }
|
||||
}
|
||||
``
|
||||
|
||||
### 3. 观察者模式(Observer Pattern)
|
||||
|
||||
类似于事件驱动架构,但更加面向对象。每个实体可以作为观察者或被观察者。
|
||||
|
||||
``csharp
|
||||
public interface IObserver
|
||||
{
|
||||
void Update(ISubject subject);
|
||||
}
|
||||
|
||||
public interface ISubject
|
||||
{
|
||||
void Attach(IObserver observer);
|
||||
void Detach(IObserver observer);
|
||||
void Notify();
|
||||
}
|
||||
``
|
||||
|
||||
### 4. 状态机(State Machine)
|
||||
|
||||
对于有明确状态转换的实体(如导弹的飞行阶段),使用状态机可以更清晰地管理状态转换。
|
||||
|
||||
``csharp
|
||||
public enum MissileState
|
||||
{
|
||||
Idle,
|
||||
Tracking,
|
||||
Locking,
|
||||
Firing,
|
||||
Exploding
|
||||
}
|
||||
|
||||
public class Missile
|
||||
{
|
||||
public MissileState State { get; set; }
|
||||
public void ChangeState(MissileState newState) { ... }
|
||||
}
|
||||
|
||||
``csharp
|
||||
public interface IState
|
||||
{
|
||||
void Enter();
|
||||
void Update();
|
||||
void Exit();
|
||||
}
|
||||
public class MissileStateMachine
|
||||
{
|
||||
private IState currentState;
|
||||
public void ChangeState(IState newState) { ... }
|
||||
public void Update() { ... }
|
||||
}
|
||||
``
|
||||
|
||||
### 5. 命令模式(Command Pattern)
|
||||
|
||||
用于封装各种操作,使得可以轻松地添加新的交互行为。
|
||||
|
||||
``csharp
|
||||
public interface ICommand
|
||||
{
|
||||
void Execute();
|
||||
}
|
||||
|
||||
public class FireMissileCommand : ICommand
|
||||
{
|
||||
public void Execute() { ... }
|
||||
}
|
||||
``
|
||||
|
||||
## 架构组合使用
|
||||
|
||||
在实际应用中,我们将这些模式组合使用:
|
||||
|
||||
1. 使用事件驱动架构作为整体框架,处理系统中的各种事件。
|
||||
2. 采用组件系统来构建各个实体(如导弹、坦克、告警设备等)。
|
||||
3. 使用状态机来管理导弹的飞行阶段。
|
||||
4. 应用观察者模式来处理告警设备的通知机制。
|
||||
5. 使用命令模式来封装各种交互操作,如发射导弹、激活干扰设备等。
|
||||
|
||||
这种组合架构允许我们灵活地处理复杂的交互关系,同时保持代码的可维护性和可扩展性。
|
||||
|
||||
## 下一步计划
|
||||
|
||||
- 实现核心实体(导弹、坦克、告警设备、干扰设备)的基本功能。
|
||||
- 设计并实现事件系统,处理实体间的交互。
|
||||
- 开发状态机,管理导弹的飞行阶段。
|
||||
- 实现观察者模式,处理告警通知。
|
||||
- 使用命令模式封装关键操作。
|
||||
- 进行单元测试和集成测试,确保系统的正确性和稳定性。
|
||||
@ -1,56 +1,140 @@
|
||||
using ActiveProtect.SimulationEnvironment;
|
||||
using System;
|
||||
|
||||
namespace ActiveProtect.Models
|
||||
{
|
||||
public class LaserDesignator(string id, LaserDesignatorConfig laserDesignatorConfig, ISimulationManager simulationManager) : SimulationElement(id, laserDesignatorConfig.InitialPosition, new Orientation(), simulationManager)
|
||||
public class LaserDesignator : SimulationElement
|
||||
{
|
||||
public string TargetId { get; private set; } = laserDesignatorConfig.TargetId;
|
||||
public bool IsActive { get; private set; } = true;
|
||||
private const double MaxIlluminationRange = 1000; // 1公里,单位:米
|
||||
public string TargetId { get; private set; }
|
||||
public bool IsActive { get; private set; }
|
||||
public double JammingThreshold { get; private set; } = 0.0; // 将阈值调整为 0 dB
|
||||
public bool IsJammed { get; private set; } = false;
|
||||
public double MaxIlluminationRange { get; private set; }
|
||||
|
||||
public void ActivateLaser()
|
||||
public LaserDesignator(string id, LaserDesignatorConfig config, ISimulationManager simulationManager)
|
||||
: base(id, config.InitialPosition, new Orientation(), simulationManager)
|
||||
{
|
||||
TargetId = config.TargetId;
|
||||
IsActive = true;
|
||||
}
|
||||
|
||||
public void DeactivateLaser()
|
||||
{
|
||||
IsActive = false;
|
||||
MaxIlluminationRange = config.MaxIlluminationRange;
|
||||
simulationManager.SubscribeToEvent<LaserJammingEvent>(OnLaserJamming);
|
||||
}
|
||||
|
||||
public override void Update(double deltaTime)
|
||||
{
|
||||
|
||||
if (IsActive)
|
||||
if (IsActive && !IsJammed)
|
||||
{
|
||||
IlluminateTarget();
|
||||
}
|
||||
else
|
||||
{
|
||||
StopIllumination();
|
||||
}
|
||||
}
|
||||
|
||||
private void IlluminateTarget()
|
||||
{
|
||||
var target = SimulationManager.GetEntityById(TargetId) as ILaserIlluminatable;
|
||||
if (target != null)
|
||||
if (SimulationManager.GetEntityById(TargetId) is ILaserIlluminatable target)
|
||||
{
|
||||
double distanceToTarget = Vector3D.Distance(Position, target.Position);
|
||||
if (distanceToTarget <= MaxIlluminationRange)
|
||||
{
|
||||
target.Illuminate();
|
||||
Console.WriteLine($"激光目标指示器 {Id} 正在照射目标 {TargetId}");
|
||||
|
||||
// 发布LaserIlluminationEvent
|
||||
PublishEvent(new LaserIlluminationEvent
|
||||
{
|
||||
TargetId = TargetId
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
target.StopIllumination();
|
||||
StopIllumination();
|
||||
Console.WriteLine($"激光目标指示器 {Id} 超出照射范围,停止照射目标 {TargetId}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void StopIllumination()
|
||||
{
|
||||
if (SimulationManager.GetEntityById(TargetId) is ILaserIlluminatable target)
|
||||
{
|
||||
target.StopIllumination();
|
||||
Console.WriteLine($"激光目标指示器 {Id} 停止照射目标 {TargetId}");
|
||||
PublishIlluminationStopEvent();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnLaserJamming(LaserJammingEvent evt)
|
||||
{
|
||||
if (evt.TargetId == TargetId)
|
||||
{
|
||||
if (SimulationManager.GetEntityById(TargetId) is Tank target)
|
||||
{
|
||||
double distanceToTarget = Vector3D.Distance(Position, target.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)
|
||||
{
|
||||
if (!IsJammed)
|
||||
{
|
||||
Console.WriteLine($"激光目标指示器 {Id} 被干扰,停止工作");
|
||||
IsJammed = true;
|
||||
DeactivateLaser();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IsJammed)
|
||||
{
|
||||
Console.WriteLine($"激光目标指示器 {Id} 干扰解除,恢复工作");
|
||||
IsJammed = false;
|
||||
ActivateLaser();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ActivateLaser()
|
||||
{
|
||||
IsActive = true;
|
||||
IsJammed = false;
|
||||
Console.WriteLine($"激光目标指示器 {Id} 已激活");
|
||||
IlluminateTarget(); // 立即开始照射目标
|
||||
}
|
||||
|
||||
public void DeactivateLaser()
|
||||
{
|
||||
if (IsActive)
|
||||
{
|
||||
IsActive = false;
|
||||
StopIllumination();
|
||||
Console.WriteLine($"激光目标指示器 {Id} 已停用");
|
||||
}
|
||||
}
|
||||
|
||||
private void PublishIlluminationStopEvent()
|
||||
{
|
||||
PublishEvent(new LaserIlluminationStopEvent
|
||||
{
|
||||
TargetId = TargetId
|
||||
});
|
||||
}
|
||||
|
||||
public override string GetStatus()
|
||||
{
|
||||
return $"激光目标指示器 {Id}:\n" +
|
||||
$" 位置: {Position}\n" +
|
||||
$" 目标: {TargetId}\n" +
|
||||
$" 激活状态: {(IsActive ? "激活" : "未激活")}";
|
||||
$" 激活状态: {(IsActive ? "激活" : "未激活")}\n" +
|
||||
$" 干扰状态: {(IsJammed ? "被干扰" : "正常")}\n" +
|
||||
$" 最大照射范围: {MaxIlluminationRange}";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
74
Models/LaserJammer.cs
Normal file
74
Models/LaserJammer.cs
Normal file
@ -0,0 +1,74 @@
|
||||
using System;
|
||||
using ActiveProtect.SimulationEnvironment;
|
||||
|
||||
namespace ActiveProtect.Models
|
||||
{
|
||||
public class LaserJammer
|
||||
{
|
||||
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; // 每秒增加的功率
|
||||
|
||||
public LaserJammer(Tank tank)
|
||||
{
|
||||
this.tank = tank;
|
||||
IsJamming = false;
|
||||
JammingPower = 0;
|
||||
tank.SimulationManager.SubscribeToEvent<LaserIlluminationStopEvent>(OnLaserIlluminationStop);
|
||||
}
|
||||
|
||||
public void Update(double deltaTime)
|
||||
{
|
||||
if (IsJamming)
|
||||
{
|
||||
// 逐渐增加干扰功率
|
||||
JammingPower = Math.Min(JammingPower + PowerIncreaseRate * deltaTime, MaxJammingPower);
|
||||
|
||||
jammingCooldown += deltaTime;
|
||||
if (jammingCooldown >= MaxJammingCooldown)
|
||||
{
|
||||
StopJamming();
|
||||
}
|
||||
|
||||
Console.WriteLine($"坦克 {tank.Id} 的激光干扰器正在工作,当前功率: {JammingPower:F2}");
|
||||
}
|
||||
else if (tank.LaserWarner.IsAlarming)
|
||||
{
|
||||
StartJamming();
|
||||
}
|
||||
}
|
||||
|
||||
private void StartJamming()
|
||||
{
|
||||
IsJamming = true;
|
||||
JammingPower = InitialJammingPower; // 从初始功率开始
|
||||
jammingCooldown = 0;
|
||||
Console.WriteLine($"坦克 {tank.Id} 的激光干扰器开始工作,初始功率: {JammingPower:F2}");
|
||||
}
|
||||
|
||||
private void StopJamming()
|
||||
{
|
||||
if (IsJamming)
|
||||
{
|
||||
IsJamming = false;
|
||||
JammingPower = 0;
|
||||
jammingCooldown = 0;
|
||||
Console.WriteLine($"坦克 {tank.Id} 的激光干扰器停止工作");
|
||||
}
|
||||
}
|
||||
|
||||
private void OnLaserIlluminationStop(LaserIlluminationStopEvent evt)
|
||||
{
|
||||
if (evt.TargetId == tank.Id)
|
||||
{
|
||||
Console.WriteLine($"坦克 {tank.Id} 接收到激光照射停止事件,停止干扰");
|
||||
StopJamming();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,15 +1,13 @@
|
||||
using ActiveProtect.SimulationEnvironment;
|
||||
using System;
|
||||
|
||||
namespace ActiveProtect.Models
|
||||
{
|
||||
public class LaserSemiActiveGuidedMissile : Missile
|
||||
{
|
||||
// 添加新的属性
|
||||
public bool IsLaserDetected { get; private set; } = false;
|
||||
private const double LaserLockDistance = 1000; // 1公里,单位:米
|
||||
|
||||
// 激光半主动制导导弹的特殊属性
|
||||
public bool IsLaserLocked { get; private set; } = false;
|
||||
private const double LaserLockDistance = 1000; // 1公里,单位:米
|
||||
|
||||
public LaserSemiActiveGuidedMissile(
|
||||
string id,
|
||||
@ -23,18 +21,20 @@ namespace ActiveProtect.Models
|
||||
public override void Update(double deltaTime)
|
||||
{
|
||||
base.Update(deltaTime);
|
||||
|
||||
// 更新激光检测和锁定逻辑
|
||||
UpdateLaserDetection();
|
||||
if (IsLaserDetected)
|
||||
{
|
||||
UpdateLaserLock();
|
||||
IsGuidanceLost = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
LoseGuidance();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateLaserDetection()
|
||||
{
|
||||
// 检查是否有激光照射目标
|
||||
var target = SimulationManager.GetEntityById(TargetId) as ILaserIlluminatable;
|
||||
if (target != null)
|
||||
{
|
||||
@ -48,13 +48,10 @@ namespace ActiveProtect.Models
|
||||
|
||||
private void UpdateLaserLock()
|
||||
{
|
||||
// 如果检测到激光,则锁定目标
|
||||
IsLaserLocked = IsLaserDetected;
|
||||
|
||||
if (IsLaserLocked)
|
||||
{
|
||||
// 根据激光照射的光斑进行导引
|
||||
// 这里可以添加更精确的导引逻辑
|
||||
AdjustTrajectoryBasedOnLaserGuidance();
|
||||
}
|
||||
}
|
||||
@ -62,14 +59,25 @@ namespace ActiveProtect.Models
|
||||
private void AdjustTrajectoryBasedOnLaserGuidance()
|
||||
{
|
||||
// 实现基于激光导引的轨迹调整
|
||||
// 这里可以添加更复杂的导引算法
|
||||
// 这里可以添加更精确的导引逻辑
|
||||
}
|
||||
|
||||
protected override void LoseGuidance()
|
||||
{
|
||||
if (!IsLaserDetected)
|
||||
{
|
||||
base.LoseGuidance();
|
||||
IsLaserLocked = false;
|
||||
Console.WriteLine($"激光半主动制导导弹 {Id} 失去激光引导");
|
||||
}
|
||||
}
|
||||
|
||||
public override string GetStatus()
|
||||
{
|
||||
return base.GetStatus().Replace("导弹", "激光半主动制导导弹") +
|
||||
$"\n 激光检测: {(IsLaserDetected ? "是" : "否")}" +
|
||||
$"\n 激光锁定: {(IsLaserLocked ? "是" : "否")}";
|
||||
string baseStatus = base.GetStatus().Replace("导弹", "激光半主动制导导弹");
|
||||
string additionalStatus = $"\n 激光检测: {(IsLaserDetected ? "是" : "否")}" +
|
||||
$"\n 激光锁定: {(IsLaserLocked ? "是" : "否")}";
|
||||
return baseStatus + additionalStatus;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
69
Models/LaserWarner.cs
Normal file
69
Models/LaserWarner.cs
Normal file
@ -0,0 +1,69 @@
|
||||
using ActiveProtect.SimulationEnvironment;
|
||||
using System;
|
||||
|
||||
namespace ActiveProtect.Models
|
||||
{
|
||||
public class LaserWarner
|
||||
{
|
||||
private readonly Tank tank;
|
||||
public bool IsAlarming { get; private set; }
|
||||
private double alarmDuration = 5.0; // 警报持续5秒
|
||||
private double alarmTimer = 0;
|
||||
|
||||
public LaserWarner(Tank tank)
|
||||
{
|
||||
this.tank = tank;
|
||||
IsAlarming = false;
|
||||
tank.SimulationManager.SubscribeToEvent<LaserIlluminationEvent>(OnLaserIllumination);
|
||||
tank.SimulationManager.SubscribeToEvent<LaserIlluminationStopEvent>(OnLaserIlluminationStop);
|
||||
}
|
||||
|
||||
public void Update(double deltaTime)
|
||||
{
|
||||
if (IsAlarming)
|
||||
{
|
||||
alarmTimer += deltaTime;
|
||||
if (alarmTimer >= alarmDuration)
|
||||
{
|
||||
StopAlarm();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnLaserIllumination(LaserIlluminationEvent evt)
|
||||
{
|
||||
if (evt.TargetId == tank.Id)
|
||||
{
|
||||
TriggerAlarm();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnLaserIlluminationStop(LaserIlluminationStopEvent evt)
|
||||
{
|
||||
if (evt.TargetId == tank.Id)
|
||||
{
|
||||
StopAlarm();
|
||||
}
|
||||
}
|
||||
|
||||
public void TriggerAlarm()
|
||||
{
|
||||
if (!IsAlarming)
|
||||
{
|
||||
IsAlarming = true;
|
||||
alarmTimer = 0;
|
||||
Console.WriteLine($"坦克 {tank.Id} 的激光告警器发出警报!");
|
||||
}
|
||||
}
|
||||
|
||||
public void StopAlarm()
|
||||
{
|
||||
if (IsAlarming)
|
||||
{
|
||||
IsAlarming = false;
|
||||
alarmTimer = 0;
|
||||
Console.WriteLine($"坦克 {tank.Id} 的激光告警器停止警报");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -26,41 +26,7 @@ namespace ActiveProtect.Models
|
||||
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;
|
||||
|
||||
/// <summary>
|
||||
/// 标准导弹的预设配置, 所有阶段都启用
|
||||
/// </summary>
|
||||
public static FlightStageConfig StandardMissile => new(enableLaunch: true, enableAcceleration: true, enableCruise: true, enableTerminalGuidance: true, enableAttack: true);
|
||||
|
||||
/// <summary>
|
||||
/// 激光制导炮弹的预设配置, 没有加速阶段
|
||||
/// </summary>
|
||||
public static FlightStageConfig LaserGuidedShell => new(enableAcceleration: false);
|
||||
|
||||
/// <summary>
|
||||
/// 短程导弹的预设配置,没有巡航阶段
|
||||
/// </summary>
|
||||
public static FlightStageConfig ShortRangeMissile => new(enableCruise: false);
|
||||
|
||||
/// <summary>
|
||||
/// 激光半主动制导导弹的预设配置, 没有加速阶段
|
||||
/// </summary>
|
||||
public static FlightStageConfig LaserSemiActiveGuidedMissile => new(enableAcceleration: false);
|
||||
}
|
||||
|
||||
|
||||
public double Speed { get; protected set; }
|
||||
public double MaxSpeed { get; protected set; }
|
||||
@ -87,6 +53,10 @@ namespace ActiveProtect.Models
|
||||
|
||||
public double ProportionalNavigationCoefficient { get; set; }
|
||||
|
||||
public bool IsGuidanceLost { get; protected set; } = false;
|
||||
protected double LostGuidanceTime { get; set; } = 0;
|
||||
protected const double MaxLostGuidanceTime = 1.0; // 1秒后自毁
|
||||
|
||||
public Missile(string id, MissileConfig missileConfig, ISimulationManager simulationManager)
|
||||
: base(id, missileConfig.InitialPosition, missileConfig.InitialOrientation, simulationManager)
|
||||
{
|
||||
@ -119,6 +89,10 @@ namespace ActiveProtect.Models
|
||||
Console.WriteLine($"导弹 {Id} 的初始阶: {CurrentStage}");
|
||||
|
||||
LastTargetPosition = Position; // 初始化 LastTargetPosition
|
||||
|
||||
// 订阅相关事件
|
||||
simulationManager.SubscribeToEvent<LaserIlluminationEvent>(OnLaserIllumination);
|
||||
simulationManager.SubscribeToEvent<LaserIlluminationStopEvent>(OnLaserIlluminationStop);
|
||||
}
|
||||
|
||||
public override void Update(double deltaTime)
|
||||
@ -152,7 +126,7 @@ namespace ActiveProtect.Models
|
||||
FlightTime += deltaTime;
|
||||
FlightDistance += Speed * deltaTime;
|
||||
|
||||
UpdateDistanceToTarget(Vector3D.Distance(Position, SimulationManager.GetElementPosition(TargetId)));
|
||||
UpdateDistanceToTarget(Vector3D.Distance(Position, SimulationManager.GetEntityById(TargetId).Position));
|
||||
|
||||
// 首先检查是否命中目标
|
||||
if (CheckHit())
|
||||
@ -170,6 +144,22 @@ namespace ActiveProtect.Models
|
||||
|
||||
// 更新飞行阶段
|
||||
UpdateFlightStage();
|
||||
|
||||
if (IsGuidanceLost)
|
||||
{
|
||||
HandleLostGuidance(deltaTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 重置失去引导的时间
|
||||
LostGuidanceTime = 0;
|
||||
}
|
||||
|
||||
// 发布事件示例
|
||||
if (CurrentStage == FlightStage.Launch)
|
||||
{
|
||||
PublishEvent(new MissileFireEvent { TargetId = TargetId });
|
||||
}
|
||||
}
|
||||
|
||||
private bool CheckHit()
|
||||
@ -192,7 +182,7 @@ namespace ActiveProtect.Models
|
||||
|
||||
private (Vector3D, Vector3D) CalculateDerivatives(Vector3D position, Vector3D velocity, double deltaTime)
|
||||
{
|
||||
Vector3D targetPosition = SimulationManager.GetElementPosition(TargetId);
|
||||
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()
|
||||
@ -266,6 +256,7 @@ namespace ActiveProtect.Models
|
||||
public void Explode()
|
||||
{
|
||||
IsActive = false;
|
||||
SimulationManager.HandleTargetHit(TargetId, Id);
|
||||
Console.WriteLine($"导弹 {Id} 在 {Position} 爆炸,命中目标!");
|
||||
}
|
||||
|
||||
@ -273,8 +264,9 @@ namespace ActiveProtect.Models
|
||||
{
|
||||
IsActive = false;
|
||||
string reason = FlightTime >= MaxFlightTime ? "超出最大飞行时间" :
|
||||
FlightDistance >= MaxFlightDistance ? "超出最大飞行距<E8A18C><E8B79D><EFBFBD>" :
|
||||
Position.Y <= 0 ? "高度小于等于0" : "未知原因";
|
||||
FlightDistance >= MaxFlightDistance ? "超出最大飞行距" :
|
||||
Position.Y <= 0 ? "高度小于等于0" :
|
||||
IsGuidanceLost ? "失去引导" : "未知原因";
|
||||
|
||||
Console.WriteLine($"导弹 {Id} 自毁。原因: {reason}");
|
||||
}
|
||||
@ -288,7 +280,9 @@ namespace ActiveProtect.Models
|
||||
$" 飞行时间: {FlightTime:F2}/{MaxFlightTime:F2}\n" +
|
||||
$" 飞行距离: {FlightDistance:F2}/{MaxFlightDistance:F2}\n" +
|
||||
$" 距离目标: {DistanceToTarget:F2}\n" +
|
||||
$" 发动机工作时间: {EngineBurnTime:F2}/{MaxEngineBurnTime:F2}";
|
||||
$" 发动机工作时间: {EngineBurnTime:F2}/{MaxEngineBurnTime:F2}\n" +
|
||||
$" 失去引导: {(IsGuidanceLost ? "是" : "否")}\n" +
|
||||
$" 失去引导时间: {LostGuidanceTime:F2}/{MaxLostGuidanceTime:F2}";
|
||||
}
|
||||
|
||||
public void SetProportionalNavigationCoefficient(double newCoefficient)
|
||||
@ -296,6 +290,53 @@ namespace ActiveProtect.Models
|
||||
ProportionalNavigationCoefficient = newCoefficient;
|
||||
Console.WriteLine($"导弹 {Id} 的比例导引系数已更新为 {newCoefficient}");
|
||||
}
|
||||
|
||||
protected virtual void LoseGuidance()
|
||||
{
|
||||
if (!IsGuidanceLost)
|
||||
{
|
||||
Console.WriteLine($"导弹 {Id} 失去引导");
|
||||
IsGuidanceLost = true;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void HandleLostGuidance(double deltaTime)
|
||||
{
|
||||
LostGuidanceTime += deltaTime;
|
||||
if (LostGuidanceTime >= MaxLostGuidanceTime)
|
||||
{
|
||||
Console.WriteLine($"导弹 {Id} 失去引导超过 {MaxLostGuidanceTime} 秒,自毁");
|
||||
SelfDestruct();
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
108
Models/Tank.cs
108
Models/Tank.cs
@ -1,39 +1,70 @@
|
||||
using ActiveProtect.SimulationEnvironment;
|
||||
using System;
|
||||
|
||||
namespace ActiveProtect.Models
|
||||
{
|
||||
public class Tank : SimulationElement, ILaserIlluminatable
|
||||
{
|
||||
public double Speed { get; set; } = 0;
|
||||
public bool IsActive { get; private set; } = false;
|
||||
public double MaxSpeed { get; private set; } = 0;
|
||||
public double MaxArmor { get; private set; } = 0;
|
||||
public double Armor { get; private set; } = 0;
|
||||
public double CurrentArmor { get; private 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)
|
||||
{
|
||||
Position = tankConfig.InitialPosition;
|
||||
Orientation = tankConfig.InitialOrientation;
|
||||
Speed = tankConfig.InitialSpeed;
|
||||
IsActive = true;
|
||||
MaxSpeed = tankConfig.MaxSpeed;
|
||||
MaxArmor = tankConfig.MaxArmor;
|
||||
Armor = tankConfig.MaxArmor;
|
||||
CurrentArmor = tankConfig.MaxArmor;
|
||||
IsIlluminated = false;
|
||||
SimulationManager = simulationManager;
|
||||
LaserWarner = new LaserWarner(this);
|
||||
LaserJammer = new LaserJammer(this);
|
||||
|
||||
// 移除事件订阅,因为现在由LaserWarner直接处理
|
||||
}
|
||||
|
||||
public void TakeDamage(double damage)
|
||||
public override void Update(double deltaTime)
|
||||
{
|
||||
CurrentArmor -= damage;
|
||||
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)
|
||||
{
|
||||
Vector3D direction = Orientation.ToVector();
|
||||
Vector3D movement = direction * Speed * deltaTime;
|
||||
Position += movement;
|
||||
}
|
||||
|
||||
public void TakeDamage(double damage, bool isMissileDamage = false)
|
||||
{
|
||||
if (isMissileDamage)
|
||||
{
|
||||
damage = CurrentArmor * 0.5;
|
||||
}
|
||||
|
||||
CurrentArmor = Math.Max(0, CurrentArmor - damage);
|
||||
if (CurrentArmor <= 0)
|
||||
{
|
||||
CurrentArmor = 0;
|
||||
IsActive = false;
|
||||
PublishEvent(new EntityDestroyedEvent { DestroyedEntityId = Id });
|
||||
}
|
||||
}
|
||||
|
||||
@ -47,49 +78,18 @@ namespace ActiveProtect.Models
|
||||
IsIlluminated = false;
|
||||
}
|
||||
|
||||
public override void Update(double deltaTime)
|
||||
{
|
||||
// 移除对基类抽象方法的调用
|
||||
// 实现坦克特定的更新逻辑
|
||||
UpdatePosition(deltaTime);
|
||||
UpdateArmor();
|
||||
CheckIlluminationStatus();
|
||||
}
|
||||
|
||||
private void UpdatePosition(double deltaTime)
|
||||
{
|
||||
// 根据速度更新坦克位置
|
||||
Vector3D direction = Orientation.ToVector();
|
||||
Vector3D movement = direction * Speed * deltaTime;
|
||||
Position += movement;
|
||||
}
|
||||
|
||||
private void UpdateArmor()
|
||||
{
|
||||
// 可能的装甲恢复逻辑
|
||||
if (CurrentArmor < MaxArmor)
|
||||
{
|
||||
CurrentArmor = Math.Min(CurrentArmor + 10, MaxArmor);
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckIlluminationStatus()
|
||||
{
|
||||
// 检查激光照射状态,可能会影响坦克的其他属性
|
||||
if (IsIlluminated)
|
||||
{
|
||||
// 实现被激光照射时的效果
|
||||
}
|
||||
}
|
||||
// 移除OnLaserIllumination和OnLaserIlluminationStop方法,因为现在由LaserWarner直接处理
|
||||
|
||||
public override string GetStatus()
|
||||
{
|
||||
return base.GetStatus() +
|
||||
$"\n 速度: {Speed}" +
|
||||
$"\n 最大速度: {MaxSpeed}" +
|
||||
$"\n 装甲: {CurrentArmor}/{MaxArmor}" +
|
||||
$"\n 状态: {(IsActive ? "活动" : "已销毁")}" +
|
||||
$"\n 激光照射: {(IsIlluminated ? "是" : "否")}";
|
||||
return $"坦克 {Id}:\n" +
|
||||
$" 位置: {Position}\n" +
|
||||
$" 速度: {Speed:F2}/{MaxSpeed:F2}\n" +
|
||||
$" 装甲: {CurrentArmor:F2}/{MaxArmor:F2}\n" +
|
||||
$" 状态: {(IsActive ? "活动" : "已销毁")}\n" +
|
||||
$" 激光照射: {(IsIlluminated ? "是" : "否")}\n" +
|
||||
$" 激光报警: {(LaserWarner.IsAlarming ? "警报中" : "正常")}\n" +
|
||||
$" 激光干扰: {(LaserJammer.IsJamming ? $"干扰中 (功率: {LaserJammer.JammingPower:F2})" : "未干扰")}";
|
||||
}
|
||||
}
|
||||
}
|
||||
20
Program.cs
20
Program.cs
@ -37,7 +37,7 @@ namespace ActiveProtect
|
||||
MaxEngineBurnTime = 5,
|
||||
MaxAcceleration = 100,
|
||||
ProportionalNavigationCoefficient = 3,
|
||||
StageConfig = Missile.FlightStageConfig.StandardMissile,
|
||||
StageConfig = FlightStageConfig.StandardMissile,
|
||||
DistanceParams = new MissileDistanceParams(500, 100, 20),
|
||||
Type = MissileType.StandardMissile
|
||||
},
|
||||
@ -54,7 +54,7 @@ namespace ActiveProtect
|
||||
MaxEngineBurnTime = 5,
|
||||
MaxAcceleration = 100,
|
||||
ProportionalNavigationCoefficient = 3,
|
||||
StageConfig = Missile.FlightStageConfig.LaserGuidedShell,
|
||||
StageConfig = FlightStageConfig.LaserGuidedShell,
|
||||
DistanceParams = new MissileDistanceParams(300, 100, 20),
|
||||
Type = MissileType.InfraredCommandGuidance
|
||||
},
|
||||
@ -71,13 +71,13 @@ namespace ActiveProtect
|
||||
MaxEngineBurnTime = 5,
|
||||
MaxAcceleration = 100,
|
||||
ProportionalNavigationCoefficient = 3,
|
||||
StageConfig = Missile.FlightStageConfig.ShortRangeMissile,
|
||||
StageConfig = FlightStageConfig.ShortRangeMissile,
|
||||
DistanceParams = new MissileDistanceParams(400, 100, 20),
|
||||
Type = MissileType.MillimeterWaveTerminalGuidance
|
||||
},
|
||||
// 新增激光半主动制导导弹配置
|
||||
new() {
|
||||
InitialPosition = new Vector3D(1500, 150, 100),
|
||||
InitialPosition = new Vector3D(2000, 150, 100),
|
||||
InitialOrientation = new Orientation(Math.PI, -0.12, 0),
|
||||
InitialSpeed = 700,
|
||||
MaxSpeed = 800,
|
||||
@ -88,7 +88,7 @@ namespace ActiveProtect
|
||||
MaxEngineBurnTime = 5,
|
||||
MaxAcceleration = 100,
|
||||
ProportionalNavigationCoefficient = 3,
|
||||
StageConfig = Missile.FlightStageConfig.LaserSemiActiveGuidedMissile,
|
||||
StageConfig = FlightStageConfig.LaserSemiActiveGuidedMissile,
|
||||
DistanceParams = new MissileDistanceParams(500, 200, 20),
|
||||
Type = MissileType.SemiActiveLaserGuidance
|
||||
}
|
||||
@ -97,8 +97,9 @@ namespace ActiveProtect
|
||||
[
|
||||
new LaserDesignatorConfig
|
||||
{
|
||||
InitialPosition = new Vector3D(500, 50, 100),
|
||||
TargetId = "Tank_1"
|
||||
InitialPosition = new Vector3D(500, 150, 100),
|
||||
TargetId = "Tank_1",
|
||||
MaxIlluminationRange = 1000
|
||||
}
|
||||
],
|
||||
SimulationTimeStep = 0.05
|
||||
@ -108,11 +109,14 @@ namespace ActiveProtect
|
||||
var simulationManager = new SimulationManager(config);
|
||||
|
||||
// 运行仿真
|
||||
while (!simulationManager.IsSimulationEnded)
|
||||
int maxIterations = 1000; // 增加最大迭代次数
|
||||
int iteration = 0;
|
||||
while (!simulationManager.IsSimulationEnded && iteration < maxIterations)
|
||||
{
|
||||
simulationManager.Update();
|
||||
simulationManager.PrintStatus();
|
||||
Thread.Sleep(100); // 暂停100毫秒,使输出更易读
|
||||
iteration++;
|
||||
}
|
||||
|
||||
Console.WriteLine("仿真结束");
|
||||
|
||||
@ -1,12 +0,0 @@
|
||||
using ActiveProtect.Models;
|
||||
using ActiveProtect.SimulationEnvironment;
|
||||
|
||||
namespace ActiveProtect.SimulationEnvironment
|
||||
{
|
||||
public interface ISimulationManager
|
||||
{
|
||||
Vector3D GetElementPosition(string elementId);
|
||||
|
||||
SimulationElement GetEntityById(string id);
|
||||
}
|
||||
}
|
||||
@ -44,7 +44,7 @@ namespace ActiveProtect.SimulationEnvironment
|
||||
public double MaxFlightDistance { get; set; }
|
||||
public double MaxAcceleration { get; set; }
|
||||
public double ProportionalNavigationCoefficient { get; set; }
|
||||
public Missile.FlightStageConfig StageConfig { get; set; }
|
||||
public FlightStageConfig StageConfig { get; set; }
|
||||
public MissileDistanceParams DistanceParams { get; set; }
|
||||
public double ThrustAcceleration { get; set; }
|
||||
public double MaxEngineBurnTime { get; set; }
|
||||
@ -60,7 +60,7 @@ namespace ActiveProtect.SimulationEnvironment
|
||||
TargetIndex = 0; // 目标索引
|
||||
MaxFlightTime = 0; // 最大飞行时间
|
||||
MaxFlightDistance = 0; // 最大飞行距离
|
||||
StageConfig = Missile.FlightStageConfig.StandardMissile; // 飞行阶段配置
|
||||
StageConfig = FlightStageConfig.StandardMissile; // 飞行阶段配置
|
||||
ThrustAcceleration = 0; // 推力加速度
|
||||
MaxEngineBurnTime = 0; // 最大发动机燃烧时间
|
||||
MaxAcceleration = 0; // 最大加速度
|
||||
@ -74,11 +74,12 @@ namespace ActiveProtect.SimulationEnvironment
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -88,4 +89,40 @@ namespace ActiveProtect.SimulationEnvironment
|
||||
public double AttackDistance { get; set; } = attackDistance;
|
||||
public double ExplosionDistance { get; set; } = explosionDistance;
|
||||
}
|
||||
|
||||
/// <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;
|
||||
|
||||
/// <summary>
|
||||
/// 标准导弹的预设配置, 所有阶段都启用
|
||||
/// </summary>
|
||||
public static FlightStageConfig StandardMissile => new(enableLaunch: true, enableAcceleration: true, enableCruise: true, enableTerminalGuidance: true, enableAttack: true);
|
||||
|
||||
/// <summary>
|
||||
/// 激光制导炮弹的预设配置, 没有加速阶段
|
||||
/// </summary>
|
||||
public static FlightStageConfig LaserGuidedShell => new(enableAcceleration: false);
|
||||
|
||||
/// <summary>
|
||||
/// 短程导弹的预设配置,没有巡航阶段
|
||||
/// </summary>
|
||||
public static FlightStageConfig ShortRangeMissile => new(enableCruise: false);
|
||||
|
||||
/// <summary>
|
||||
/// 激光半主动制导导弹的预设配置, 没有加速阶段
|
||||
/// </summary>
|
||||
public static FlightStageConfig LaserSemiActiveGuidedMissile => new(enableAcceleration: false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -15,5 +15,12 @@ namespace ActiveProtect.SimulationEnvironment
|
||||
{
|
||||
return $"{GetType().Name} {Id} at {Position}, Orientation: {Orientation}";
|
||||
}
|
||||
|
||||
protected void PublishEvent(SimulationEvent evt)
|
||||
{
|
||||
evt.SenderId = Id;
|
||||
evt.Timestamp = SimulationManager.CurrentTime;
|
||||
SimulationManager.PublishEvent(evt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
34
SimulationEnvironment/SimulationEvents.cs
Normal file
34
SimulationEnvironment/SimulationEvents.cs
Normal file
@ -0,0 +1,34 @@
|
||||
namespace ActiveProtect.SimulationEnvironment
|
||||
{
|
||||
public class SimulationEvent
|
||||
{
|
||||
public string? SenderId { get; set; }
|
||||
public double Timestamp { get; set; }
|
||||
}
|
||||
|
||||
public class MissileFireEvent : SimulationEvent
|
||||
{
|
||||
public string? TargetId { get; set; }
|
||||
}
|
||||
|
||||
public class LaserIlluminationEvent : SimulationEvent
|
||||
{
|
||||
public string? TargetId { get; set; }
|
||||
}
|
||||
|
||||
public class LaserJammingEvent : SimulationEvent
|
||||
{
|
||||
public string? TargetId { get; set; }
|
||||
public double JammingPower { get; set; }
|
||||
}
|
||||
|
||||
public class EntityDestroyedEvent : SimulationEvent
|
||||
{
|
||||
public string? DestroyedEntityId { get; set; }
|
||||
}
|
||||
|
||||
public class LaserIlluminationStopEvent : SimulationEvent
|
||||
{
|
||||
public string? TargetId { get; set; }
|
||||
}
|
||||
}
|
||||
@ -5,12 +5,25 @@ using ActiveProtect.Models;
|
||||
|
||||
namespace ActiveProtect.SimulationEnvironment
|
||||
{
|
||||
public interface ISimulationManager
|
||||
{
|
||||
double CurrentTime { get; }
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public class SimulationManager : ISimulationManager
|
||||
{
|
||||
public List<SimulationElement> Elements { get; private set; }
|
||||
public double CurrentTime { get; private set; }
|
||||
public bool IsSimulationEnded { get; private set; }
|
||||
private readonly SimulationConfig config;
|
||||
private Dictionary<Type, List<Delegate>> eventHandlers = new Dictionary<Type, List<Delegate>>();
|
||||
|
||||
public SimulationManager(SimulationConfig config)
|
||||
{
|
||||
@ -54,7 +67,40 @@ namespace ActiveProtect.SimulationEnvironment
|
||||
for (int i = 0; i < config.LaserDesignatorConfigs.Count; i++)
|
||||
{
|
||||
var laserDesignatorConfig = config.LaserDesignatorConfigs[i];
|
||||
Elements.Add(new LaserDesignator($"LD_{i + 1}", laserDesignatorConfig, this));
|
||||
var laserDesignator = new LaserDesignator($"LD_{i + 1}", laserDesignatorConfig, this);
|
||||
Elements.Add(laserDesignator);
|
||||
laserDesignator.ActivateLaser(); // 激活激光目标指示器
|
||||
}
|
||||
}
|
||||
|
||||
public void PublishEvent(SimulationEvent evt)
|
||||
{
|
||||
var eventType = evt.GetType();
|
||||
if (eventHandlers.TryGetValue(eventType, out var handlers))
|
||||
{
|
||||
foreach (var handler in handlers)
|
||||
{
|
||||
handler.DynamicInvoke(evt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void SubscribeToEvent<T>(Action<T> handler) where T : SimulationEvent
|
||||
{
|
||||
var eventType = typeof(T);
|
||||
if (!eventHandlers.ContainsKey(eventType))
|
||||
{
|
||||
eventHandlers[eventType] = new List<Delegate>();
|
||||
}
|
||||
eventHandlers[eventType].Add(handler);
|
||||
}
|
||||
|
||||
public void UnsubscribeFromEvent<T>(Action<T> handler) where T : SimulationEvent
|
||||
{
|
||||
var eventType = typeof(T);
|
||||
if (eventHandlers.ContainsKey(eventType))
|
||||
{
|
||||
eventHandlers[eventType].Remove(handler);
|
||||
}
|
||||
}
|
||||
|
||||
@ -97,19 +143,44 @@ namespace ActiveProtect.SimulationEnvironment
|
||||
Console.WriteLine($"剩余坦克数量: {Elements.Count(e => e is Tank)}");
|
||||
}
|
||||
|
||||
public Vector3D GetElementPosition(string elementId)
|
||||
{
|
||||
var element = Elements.FirstOrDefault(e => e.Id == elementId);
|
||||
if (element != null)
|
||||
{
|
||||
return element.Position;
|
||||
}
|
||||
throw new ArgumentException($"Element with id {elementId} not found");
|
||||
}
|
||||
|
||||
public SimulationElement GetEntityById(string id)
|
||||
{
|
||||
return Elements.FirstOrDefault(e => e.Id == id) ?? throw new InvalidOperationException($"Entity with id {id} not found");
|
||||
}
|
||||
|
||||
public void HandleTargetHit(string targetId, string missileId)
|
||||
{
|
||||
if (GetEntityById(targetId) is Tank tank && GetEntityById(missileId) is Missile missile)
|
||||
{
|
||||
// 计算导弹造成的伤害
|
||||
double damage = CalculateMissileDamage(missile);
|
||||
|
||||
// 对坦克造成伤害
|
||||
tank.TakeDamage(damage, true);
|
||||
|
||||
// 移除已爆炸的导弹
|
||||
RemoveEntity(missileId);
|
||||
|
||||
// 记录击中事件
|
||||
LogHitEvent(targetId, missileId, damage);
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveEntity(string missileId)
|
||||
{
|
||||
Elements.Remove(GetEntityById(missileId));
|
||||
}
|
||||
|
||||
private double CalculateMissileDamage(Missile missile)
|
||||
{
|
||||
// 这里可以根据导弹类型、速度等因素计算伤害
|
||||
// 现在我们简单地返回一个固定值
|
||||
return 100;
|
||||
}
|
||||
|
||||
private void LogHitEvent(string targetId, string missileId, double damage)
|
||||
{
|
||||
Console.WriteLine($"目标 {targetId} 被导弹 {missileId} 击中,造成 {damage} 点伤害");
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user