400 lines
13 KiB
C#
400 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];
|
|
|
|
// 确保 MaxFlightTime 设置合理
|
|
if (missileConfig.MaxFlightTime <= 0)
|
|
{
|
|
missileConfig.MaxFlightTime = 300; // 设置一个默认值,比如 300 秒
|
|
Console.WriteLine($"警告:导弹配置 {i} 的 MaxFlightTime 无效,已设置为默认值 300 秒");
|
|
}
|
|
|
|
MissileBase missile = missileConfig.Type switch
|
|
{
|
|
MissileType.LaserSemiActiveGuidance => new LaserSemiActiveGuidedMissile(
|
|
$"LSGM_{i + 1}",
|
|
missileConfig,
|
|
"LD_1",
|
|
this
|
|
),
|
|
MissileType.LaserBeamRiderGuidance => new LaserBeamRiderMissile(
|
|
$"LBRM_{i + 1}",
|
|
"Tank_1",
|
|
missileConfig,
|
|
this
|
|
),
|
|
_ => new MissileBase(
|
|
$"NM_{i + 1}",
|
|
missileConfig,
|
|
this
|
|
),
|
|
};
|
|
Elements.Add(missile);
|
|
}
|
|
|
|
// 创建激光目标指示器
|
|
var laserDesignatorConfig = config.LaserDesignatorConfig;
|
|
var laserDesignator = new LaserDesignator(
|
|
$"LD_1",
|
|
"Tank_1",
|
|
"LSGM_1",
|
|
laserDesignatorConfig,
|
|
this
|
|
);
|
|
Elements.Add(laserDesignator);
|
|
|
|
// 创建激光驾束仪
|
|
var laserBeamRiderConfig = config.LaserBeamRiderConfig;
|
|
var laserBeamRider = new LaserBeamRider(
|
|
"LBR_1",
|
|
"LBRM_2",
|
|
"Tank_1",
|
|
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($"没有找到事件 {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);
|
|
}
|
|
}
|
|
}
|