396 lines
13 KiB
C#
396 lines
13 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>
|
||
/// 根据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($"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];
|
||
MissileBase missile;
|
||
|
||
switch (missileConfig.Type)
|
||
{
|
||
case MissileType.LaserSemiActiveGuidance:
|
||
missile = new LaserSemiActiveGuidedMissile($"LSGM_{i + 1}", missileConfig, this);
|
||
break;
|
||
case MissileType.LaserBeamRiderGuidance:
|
||
missile = new LaserBeamRiderMissile($"LBRM_{i + 1}", missileConfig, this);
|
||
break;
|
||
case MissileType.TerminalSensitiveMissile:
|
||
missile = new TerminalSensitiveMissile($"TSM_{i + 1}", missileConfig, this);
|
||
break;
|
||
default:
|
||
missile = new MissileBase($"M_{i + 1}", 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_2",
|
||
"Tank_1",
|
||
0,
|
||
laserBeamRiderConfig,
|
||
this
|
||
);
|
||
Elements.Add(laserBeamRider);
|
||
|
||
|
||
// 激活所有元素
|
||
ActivateAllElements();
|
||
|
||
// 启动激光驾束仪
|
||
laserBeamRider.StartBeamIllumination();
|
||
}
|
||
|
||
//激活所有元素
|
||
private void ActivateAllElements()
|
||
{
|
||
foreach (var element in Elements)
|
||
{
|
||
element.Activate();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 发布仿真事件
|
||
/// </summary>
|
||
public void PublishEvent(SimulationEvent evt)
|
||
{
|
||
var eventType = evt.GetType();
|
||
//Console.WriteLine($"发布事件: {eventType.Name}, 发送者: {evt.SenderId}");
|
||
if (eventHandlers.TryGetValue(eventType, out var handlers))
|
||
{
|
||
foreach (var handler in handlers)
|
||
{
|
||
handler.DynamicInvoke(evt);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine($"没<><E6B2A1>找到事件 {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($"仿真时间: {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);
|
||
}
|
||
}
|
||
}
|