463 lines
15 KiB
C#
463 lines
15 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using ActiveProtect.Models;
|
|
|
|
namespace ActiveProtect.SimulationEnvironment
|
|
{
|
|
/// <summary>
|
|
/// 仿真管理器接口,定义了仿真管理器的基本功能
|
|
/// </summary>
|
|
public interface ISimulationManager
|
|
{
|
|
/// <summary>
|
|
/// 当前仿真时间
|
|
/// </summary>
|
|
double CurrentTime { get; }
|
|
|
|
/// <summary>
|
|
/// 添加仿真元素
|
|
/// </summary>
|
|
void AddElement(SimulationElement element);
|
|
|
|
/// <summary>
|
|
/// 仿真元素列表
|
|
/// </summary>
|
|
List<SimulationElement> GetElements();
|
|
|
|
/// <summary>
|
|
/// 根据ID获取仿真实体
|
|
/// </summary>
|
|
SimulationElement GetEntityById(string id);
|
|
|
|
/// <summary>
|
|
/// 处理目标被击中事件
|
|
/// </summary>
|
|
void HandleTargetHit(string targetId, string missileId);
|
|
|
|
/// <summary>
|
|
/// 发布仿真事件
|
|
/// </summary>
|
|
void PublishEvent(SimulationEvent evt);
|
|
|
|
/// <summary>
|
|
/// 订阅仿真事件
|
|
/// </summary>
|
|
void SubscribeToEvent<T>(Action<T> handler) where T : SimulationEvent;
|
|
|
|
/// <summary>
|
|
/// 取消订阅仿真事件
|
|
/// </summary>
|
|
void UnsubscribeFromEvent<T>(Action<T> handler) where T : SimulationEvent;
|
|
|
|
/// <summary>
|
|
/// 取消所有事件订阅
|
|
/// </summary>
|
|
void UnsubscribeAllEvents(SimulationElement element);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 仿真管理器类,负责管理整个仿真过程
|
|
/// </summary>
|
|
public class SimulationManager : ISimulationManager
|
|
{
|
|
/// <summary>
|
|
/// 仿真元素列表
|
|
/// </summary>
|
|
public List<SimulationElement> Elements { get; private set; }
|
|
|
|
/// <summary>
|
|
/// 当前仿真时间
|
|
/// </summary>
|
|
public double CurrentTime { get; private set; }
|
|
|
|
/// <summary>
|
|
/// 仿真是否结束
|
|
/// </summary>
|
|
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)>>();
|
|
|
|
/// <summary>
|
|
/// 构造函数
|
|
/// </summary>
|
|
public SimulationManager(SimulationConfig config)
|
|
{
|
|
this.config = config;
|
|
Elements = new List<SimulationElement>();
|
|
CurrentTime = 0;
|
|
IsSimulationEnded = false;
|
|
InitializeSimulation();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 初始化仿真
|
|
/// </summary>
|
|
private void InitializeSimulation()
|
|
{
|
|
// 创建坦克
|
|
for (int i = 0; i < config.TankConfigs.Count; i++)
|
|
{
|
|
var tankConfig = config.TankConfigs[i];
|
|
var tank = new Tank(tankConfig, this);
|
|
Elements.Add(tank);
|
|
|
|
// 为坦克创建激光告警器
|
|
if (tankConfig.HasLaserWarner)
|
|
{
|
|
var laserWarner = new LaserWarner(
|
|
$"LW_{i}",
|
|
tank.Position,
|
|
tank.Orientation,
|
|
this,
|
|
tank.Id,
|
|
config.LaserWarnerConfig
|
|
);
|
|
Elements.Add(laserWarner);
|
|
}
|
|
|
|
// 为坦克创建激光干扰机
|
|
if (tankConfig.HasLaserJammer)
|
|
{
|
|
var laserJammer = new LaserJammer(
|
|
$"LJ_{i}",
|
|
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];
|
|
MissileBase missile;
|
|
|
|
switch (missileConfig.Type)
|
|
{
|
|
case MissileType.LaserSemiActiveGuidance:
|
|
missile = new LaserSemiActiveGuidedMissile(missileConfig, this);
|
|
break;
|
|
case MissileType.LaserBeamRiderGuidance:
|
|
missile = new LaserBeamRiderMissile(missileConfig, this);
|
|
break;
|
|
case MissileType.TerminalSensitiveMissile:
|
|
missile = new TerminalSensitiveMissile(missileConfig, this);
|
|
break;
|
|
case MissileType.InfraredCommandGuidance:
|
|
missile = new InfraredCommandGuidedMissile(missileConfig, this);
|
|
break;
|
|
case MissileType.InfraredImagingTerminalGuidance:
|
|
missile = new InfraredImagingTerminalGuidedMissile(missileConfig, this);
|
|
break;
|
|
case MissileType.MillimeterWaveTerminalGuidance:
|
|
missile = new MillimeterWaveTerminalGuidedMissile(missileConfig, this);
|
|
break;
|
|
default:
|
|
missile = new MissileBase(missileConfig, this);
|
|
break;
|
|
}
|
|
|
|
Elements.Add(missile);
|
|
}
|
|
|
|
// 创建激光目标指示器
|
|
var laserDesignatorConfig = config.LaserDesignatorConfig;
|
|
var laserDesignator = new LaserDesignator(
|
|
$"LD_1",
|
|
"Tank_1",
|
|
"LSGM_1",
|
|
0,
|
|
laserDesignatorConfig,
|
|
this
|
|
);
|
|
Elements.Add(laserDesignator);
|
|
if (Elements.FirstOrDefault(e => e.Id == "LSGM_1") is LaserSemiActiveGuidedMissile lsGM)
|
|
{
|
|
lsGM.LaserDesignatorId = "LD_1";
|
|
}
|
|
|
|
// 创建激光驾束仪
|
|
var laserBeamRiderConfig = config.LaserBeamRiderConfig;
|
|
var laserBeamRider = new LaserBeamRider(
|
|
"LBR_1",
|
|
"LBRM_1",
|
|
"Tank_1",
|
|
0,
|
|
laserBeamRiderConfig,
|
|
this
|
|
);
|
|
Elements.Add(laserBeamRider);
|
|
|
|
// 创建红外测角仪
|
|
var infraredTrackerConfig = config.InfraredTrackerConfig;
|
|
var infraredTracker = new InfraredTracker(
|
|
"IT_1",
|
|
"Tank_1",
|
|
infraredTrackerConfig,
|
|
this
|
|
);
|
|
Elements.Add(infraredTracker);
|
|
|
|
// 激活所有元素
|
|
ActivateAllElements();
|
|
|
|
// 激活部分元素
|
|
//ActivateSomeElements();
|
|
}
|
|
|
|
//激活所有元素
|
|
private void ActivateAllElements()
|
|
{
|
|
foreach (var element in Elements)
|
|
{
|
|
element.Activate();
|
|
}
|
|
}
|
|
// 激活部分元素
|
|
private void ActivateSomeElements()
|
|
{
|
|
// 激活坦克
|
|
Elements.FindAll(e => e.Id == "Tank_1").ForEach(e => e.Activate());
|
|
|
|
// 激活激光告警器
|
|
//Elements.FindAll(e => e.Id == "LW_1").ForEach(e => e.Activate());
|
|
|
|
// 激活激光干扰器
|
|
//Elements.FindAll(e => e.Id == "LJ_1").ForEach(e => e.Activate());
|
|
|
|
// 激活激光半主动制导导弹
|
|
//Elements.FindAll(e => e.Id == "LSGM_1").ForEach(e => e.Activate());
|
|
// 激活激光目标指示器
|
|
//Elements.FindAll(e => e.Id == "LD_1").ForEach(e => e.Activate());
|
|
|
|
// 激活激光驾束制导导弹
|
|
//Elements.FindAll(e => e.Id == "LBRM_1").ForEach(e => e.Activate());
|
|
// 激活激光驾束仪
|
|
//Elements.FindAll(e => e.Id == "LBR_1").ForEach(e => e.Activate());
|
|
|
|
// 激活红外指令制导导弹
|
|
Elements.FindAll(e => e.Id == "ICGM_1").ForEach(e => e.Activate());
|
|
// 激活红外测角仪
|
|
Elements.FindAll(e => e.Id == "IT_1").ForEach(e => e.Activate());
|
|
|
|
// 激活红外成像末制导导弹
|
|
Elements.FindAll(e => e.Id == "ITGM_1").ForEach(e => e.Activate());
|
|
|
|
// 激活毫米波末制导导弹
|
|
//Elements.FindAll(e => e.Id == "MMWG_1").ForEach(e => e.Activate());
|
|
|
|
// 激活末敏弹
|
|
//Elements.FindAll(e => e.Id == "TSM_1").ForEach(e => e.Activate());
|
|
}
|
|
|
|
/// <summary>
|
|
/// 发布仿真事件
|
|
/// </summary>
|
|
public void PublishEvent(SimulationEvent evt)
|
|
{
|
|
var eventType = evt.GetType();
|
|
if (eventHandlers.TryGetValue(eventType, out var handlers))
|
|
{
|
|
foreach (var handler in handlers)
|
|
{
|
|
handler.DynamicInvoke(evt);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Console.WriteLine($"没找到事件 {eventType.Name} 的处理程序");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 订阅仿真事件
|
|
/// </summary>
|
|
public void SubscribeToEvent<T>(Action<T> handler) where T : SimulationEvent
|
|
{
|
|
var eventType = typeof(T);
|
|
if (!eventHandlers.TryGetValue(eventType, out List<Delegate>? value))
|
|
{
|
|
value = new List<Delegate>();
|
|
eventHandlers[eventType] = value;
|
|
}
|
|
|
|
value.Add(handler);
|
|
|
|
// 记录订阅关系
|
|
var element = Elements.FirstOrDefault(e => e.GetType().GetMethods().Any(m => m.Name == handler.Method.Name));
|
|
if (element != null)
|
|
{
|
|
if (!elementSubscriptions.TryGetValue(element, out List<(Type, Delegate)>? subscriptions))
|
|
{
|
|
subscriptions = new List<(Type, Delegate)>();
|
|
elementSubscriptions[element] = subscriptions;
|
|
}
|
|
|
|
subscriptions.Add((eventType, handler as Delegate));
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 取消订阅仿真事件
|
|
/// </summary>
|
|
public void UnsubscribeFromEvent<T>(Action<T> handler) where T : SimulationEvent
|
|
{
|
|
var eventType = typeof(T);
|
|
if (eventHandlers.TryGetValue(eventType, out List<Delegate>? value))
|
|
{
|
|
value.Remove(handler);
|
|
}
|
|
|
|
// 移除订阅关系记录
|
|
var element = Elements.FirstOrDefault(e => e.GetType().GetMethods().Any(m => m.Name == handler.Method.Name));
|
|
if (element != null && elementSubscriptions.TryGetValue(element, out List<(Type, Delegate)>? subscriptions))
|
|
{
|
|
subscriptions.RemoveAll(s => Delegate.Equals(s.Item2, handler));
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 取消所有事件订阅
|
|
/// </summary>
|
|
public void UnsubscribeAllEvents(SimulationElement element)
|
|
{
|
|
if (elementSubscriptions.ContainsKey(element))
|
|
{
|
|
foreach (var subscription in elementSubscriptions[element])
|
|
{
|
|
if (eventHandlers.TryGetValue(subscription.Item1, out List<Delegate>? value))
|
|
{
|
|
value.Remove(subscription.Item2);
|
|
}
|
|
}
|
|
elementSubscriptions.Remove(element);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 更新仿真状态
|
|
/// </summary>
|
|
public void Update()
|
|
{
|
|
if (IsSimulationEnded) return;
|
|
|
|
CurrentTime += config.SimulationTimeStep;
|
|
|
|
foreach (var element in Elements.ToList())
|
|
{
|
|
if (element.IsActive)
|
|
{
|
|
element.Update(config.SimulationTimeStep);
|
|
}
|
|
else
|
|
{
|
|
UnsubscribeAllEvents(element);
|
|
}
|
|
}
|
|
|
|
// 移除不活跃的元素
|
|
Elements.RemoveAll(e => !e.IsActive);
|
|
|
|
// 检查是否所有导弹都结束飞行
|
|
if (!Elements.Any(e => e is MissileBase && e.IsActive))
|
|
{
|
|
EndSimulation();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 打印仿真状态
|
|
/// </summary>
|
|
public void PrintStatus()
|
|
{
|
|
Console.WriteLine($"\n********** 仿真时间: {CurrentTime:F2}");
|
|
foreach (var element in Elements)
|
|
{
|
|
Console.WriteLine(element.GetStatus());
|
|
}
|
|
Console.WriteLine();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 结束仿真
|
|
/// </summary>
|
|
private void EndSimulation()
|
|
{
|
|
IsSimulationEnded = true;
|
|
Console.WriteLine("仿真结束");
|
|
Console.WriteLine($"总仿真时间: {CurrentTime:F2} 秒");
|
|
Console.WriteLine($"剩余坦克数量: {Elements.Count(e => e is Tank)}");
|
|
}
|
|
|
|
/// <summary>
|
|
/// 根据ID获取仿真实体
|
|
/// </summary>
|
|
public SimulationElement GetEntityById(string id)
|
|
{
|
|
return Elements.FirstOrDefault(e => e.Id == id) ?? throw new InvalidOperationException($"Entity with id {id} not found");
|
|
}
|
|
|
|
/// <summary>
|
|
/// 处理目标被击中事件
|
|
/// </summary>
|
|
public void HandleTargetHit(string targetId, string missileId)
|
|
{
|
|
if (GetEntityById(targetId) is Tank tank && GetEntityById(missileId) is MissileBase missile)
|
|
{
|
|
// 计算导弹造成的伤害
|
|
double damage = CalculateMissileDamage(missile);
|
|
|
|
// 对坦克造成伤害
|
|
tank.TakeDamage(damage, true);
|
|
|
|
// 记录击中事件
|
|
LogHitEvent(targetId, missileId, damage);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 计算导弹造成的伤害
|
|
/// </summary>
|
|
private double CalculateMissileDamage(MissileBase missile)
|
|
{
|
|
// 这里可以根据导弹类型、速度等因素计算伤害
|
|
// 现在我们简单地返回一个固定值
|
|
return 50;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 记录击中事件
|
|
/// </summary>
|
|
private static void LogHitEvent(string targetId, string missileId, double damage)
|
|
{
|
|
Console.WriteLine($"目标 {targetId} 被导弹 {missileId} 击中,造成 {damage} 点伤害");
|
|
}
|
|
|
|
/// <summary>
|
|
/// 添加仿真元素
|
|
/// </summary>
|
|
public void AddElement(SimulationElement element)
|
|
{
|
|
Elements.Add(element);
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// 获取仿真元素列表
|
|
/// </summary>
|
|
public List<SimulationElement> GetElements()
|
|
{
|
|
return Elements;
|
|
}
|
|
}
|
|
}
|