1504 lines
60 KiB
C#
1504 lines
60 KiB
C#
using ThreatSource.Missile;
|
||
using ThreatSource.Simulation;
|
||
using ThreatSource.Utils;
|
||
using ThreatSource.Jammable;
|
||
using ThreatSource.Jammer;
|
||
using ThreatSource.Equipment;
|
||
using ThreatSource.Indicator;
|
||
using ThreatSource.Data;
|
||
using System.Diagnostics;
|
||
|
||
namespace ThreatSource.Tools.MissileSimulation
|
||
{
|
||
/// <summary>
|
||
/// 综合导弹模拟器 - 支持6种不同类型的导弹模拟
|
||
/// </summary>
|
||
public class ComprehensiveMissileSimulator
|
||
{
|
||
// 定义仿真结束事件
|
||
public event EventHandler? SimulationEnded;
|
||
|
||
private ConsoleTraceListener consoleListener;
|
||
private EventTypeFilter logLevelFilter;
|
||
|
||
private readonly SimulationManager simulationManager;
|
||
private readonly ThreatSourceFactory _threatSourceFactory;
|
||
private readonly ThreatSourceDataManager _dataManager;
|
||
private readonly Dictionary<string, BaseMissile> missiles;
|
||
private readonly Dictionary<string, SimulationElement> targets;
|
||
private readonly Dictionary<string, SimulationElement> indicators;
|
||
private readonly Dictionary<string, BaseJammer> jammers;
|
||
private readonly Dictionary<string, bool> missileActiveStatus;
|
||
public double TimeStep { get; set; } = 0.02; // 时间步长,单位:秒,默认为低精度
|
||
|
||
// 导弹-干扰映射表
|
||
private Dictionary<string, List<(JammingType Type, string DisplayName, string JammerId, string Mode, string Target)>> missileJammingMap;
|
||
|
||
// 当前选中的导弹ID
|
||
public string SelectedMissileId { get; private set; }
|
||
|
||
private List<(JammingType Type, string DisplayName, string JammerId, string Mode, string Target)> activeJammings;
|
||
|
||
/// <summary>
|
||
/// 获取当前选中导弹的显示名称
|
||
/// </summary>
|
||
public string SelectedMissileDisplayName
|
||
{
|
||
get
|
||
{
|
||
return SelectedMissileId switch
|
||
{
|
||
"LSGM_1" => "激光半主动制导导弹",
|
||
"LBRM_1" => "激光驾束制导导弹",
|
||
"TSM_1" => "末敏子弹药",
|
||
"ICGM_1" => "红外指令制导导弹",
|
||
"ITGM_1" => "红外成像末制导导弹",
|
||
"MMWG_1" => "毫米波末制导导弹",
|
||
"CGGM_1" => "毫米波/红外复合制导导弹",
|
||
"CGGM_2" => "激光/红外复合制导导弹",
|
||
_ => "未知导弹",
|
||
};
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 初始化综合导弹模拟器
|
||
/// </summary>
|
||
public ComprehensiveMissileSimulator()
|
||
{
|
||
// 首先初始化过滤器和监听器
|
||
logLevelFilter = new EventTypeFilter(SourceLevels.Verbose); // 默认设置为Verbose
|
||
consoleListener = new ConsoleTraceListener
|
||
{
|
||
Filter = logLevelFilter
|
||
};
|
||
|
||
// 清除任何现有的ConsoleTraceListeners并添加我们的控制实例
|
||
for (int i = Trace.Listeners.Count - 1; i >= 0; i--)
|
||
{
|
||
if (Trace.Listeners[i] is ConsoleTraceListener)
|
||
{
|
||
Trace.Listeners.RemoveAt(i);
|
||
}
|
||
}
|
||
Trace.Listeners.Add(consoleListener);
|
||
|
||
simulationManager = new SimulationManager();
|
||
_dataManager = new ThreatSourceDataManager("../ThreatSource/data");
|
||
_threatSourceFactory = new ThreatSourceFactory(_dataManager, simulationManager);
|
||
missiles = [];
|
||
targets = [];
|
||
indicators = [];
|
||
jammers = [];
|
||
missileActiveStatus = [];
|
||
missileJammingMap = [];
|
||
SelectedMissileId = "";
|
||
|
||
activeJammings = [];
|
||
|
||
// 初始化导弹-干扰映射
|
||
InitializeMissileJammingMap();
|
||
}
|
||
|
||
public SourceLevels CurrentLogLevel => logLevelFilter?.EventType ?? SourceLevels.Off;
|
||
|
||
public void SetLogLevel(SourceLevels level)
|
||
{
|
||
if (logLevelFilter != null)
|
||
{
|
||
logLevelFilter.EventType = level;
|
||
Console.WriteLine($"[Simulator] 日志输出级别已设置为: {level}");
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine("[Simulator] Error: Log level filter not initialized.");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 初始化导弹-干扰映射关系
|
||
/// </summary>
|
||
private void InitializeMissileJammingMap()
|
||
{
|
||
missileJammingMap = new Dictionary<string, List<(JammingType, string, string, string, string)>>
|
||
{
|
||
// 激光驾束导弹
|
||
["LBRM_1"] =
|
||
[
|
||
(JammingType.Laser, "激光干扰", "LaserJammer_Designator", "阻塞", "驾束仪"),
|
||
(JammingType.SmokeGrenade, "烟幕弹", "SG_1", "遮蔽", "驾束仪")
|
||
],
|
||
|
||
// 激光半主动制导导弹
|
||
["LSGM_1"] =
|
||
[
|
||
(JammingType.Laser, "激光干扰(指示器)", "LaserJammer_Designator", "阻塞", "指示器"),
|
||
(JammingType.Laser, "激光干扰(导弹)", "LaserJammer_Missile", "阻塞", "导弹"),
|
||
(JammingType.LaserDecoy, "激光诱偏目标", "LDY_1", "欺骗", "导弹"),
|
||
(JammingType.SmokeGrenade, "烟幕弹", "SG_1", "遮蔽", "两者")
|
||
],
|
||
|
||
// 红外指令制导导弹
|
||
["ICGM_1"] =
|
||
[
|
||
(JammingType.Infrared, "红外干扰", "InfraredJammer_Designator", "阻塞", "指示器"),
|
||
(JammingType.SmokeGrenade, "烟幕弹", "SG_2", "遮蔽", "指示器")
|
||
],
|
||
|
||
// 红外成像末制导导弹
|
||
["ITGM_1"] =
|
||
[
|
||
(JammingType.Infrared, "红外干扰", "InfraredJammer_Missile", "阻塞", "导弹"),
|
||
(JammingType.SmokeGrenade, "红外烟幕弹", "SG_2", "遮蔽", "导弹")
|
||
],
|
||
|
||
// 毫米波末制导导弹
|
||
["MMWG_1"] =
|
||
[
|
||
(JammingType.MillimeterWave, "毫米波干扰", "MillimeterWaveJammer_Missile", "阻塞", "导弹"),
|
||
(JammingType.SmokeGrenade, "烟幕弹", "SG_3", "遮蔽", "导弹")
|
||
],
|
||
|
||
// 末敏子弹药
|
||
["TSM_1"] =
|
||
[
|
||
(JammingType.Laser, "激光干扰", "LaserJammer_Submunition", "阻塞", "子弹药"),
|
||
(JammingType.Infrared, "红外干扰", "InfraredJammer_Submunition", "阻塞", "子弹药"),
|
||
(JammingType.MillimeterWave, "毫米波干扰", "MillimeterWaveJammer_Submunition", "阻塞", "子弹药"),
|
||
(JammingType.MillimeterWave, "毫米波假信号", "MillimeterWaveCompensationJammer_Submunition", "欺骗", "子弹药"),
|
||
(JammingType.SmokeGrenade, "烟幕弹", "SG_4", "遮蔽", "子弹药")
|
||
],
|
||
|
||
// 复合制导导弹
|
||
["CGGM_1"] =
|
||
[
|
||
(JammingType.MillimeterWave, "毫米波干扰", "MillimeterWaveJammer_Missile", "阻塞", "导弹"),
|
||
(JammingType.Infrared, "红外干扰", "InfraredJammer_Missile", "阻塞", "导弹"),
|
||
(JammingType.SmokeGrenade, "烟幕弹", "SG_1", "遮蔽", "导弹")
|
||
],
|
||
|
||
// 激光/红外复合制导导弹
|
||
["CGGM_2"] =
|
||
[
|
||
(JammingType.Laser, "激光干扰", "LaserJammer_Missile", "阻塞", "导弹"),
|
||
(JammingType.Infrared, "红外干扰", "InfraredJammer_Missile", "阻塞", "导弹"),
|
||
(JammingType.SmokeGrenade, "烟幕弹", "SG_1", "遮蔽", "导弹")
|
||
]
|
||
};
|
||
}
|
||
|
||
/// <summary>
|
||
/// 添加天气
|
||
/// </summary>
|
||
private void AddWeathers()
|
||
{
|
||
// 创建雨天天气并设置为当前天气
|
||
var rainWeather = _threatSourceFactory.CreateWeather("sunny");
|
||
simulationManager.SetWeather(rainWeather);
|
||
Console.WriteLine("已添加并设置晴天天气环境");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 添加目标
|
||
/// </summary>
|
||
private void AddTankTarget()
|
||
{
|
||
var motionParameters = new KinematicState
|
||
{
|
||
Position = new Vector3D(0, 1.2, 0),
|
||
Orientation = new Orientation(0.0, 0.0, 0.0),
|
||
Speed = 2.0
|
||
};
|
||
|
||
string targetId = "Tank_1";
|
||
var target = _threatSourceFactory.CreateEquipment(targetId, "mbt_001", motionParameters);
|
||
targets[targetId] = target;
|
||
simulationManager.RegisterEntity(targetId, target);
|
||
target.Activate(); // 激活目标
|
||
Console.WriteLine($"添加目标 {targetId},位置:{motionParameters.Position}");
|
||
Console.WriteLine($"目标创建后实际位置:{target.KState.Position}");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 添加激光诱偏目标
|
||
/// </summary>
|
||
private void AddLaserDecoy()
|
||
{
|
||
var motionParameters = new KinematicState
|
||
{
|
||
Position = new Vector3D(0, 0, 50),
|
||
Orientation = new Orientation(Math.PI/2, 0.0, 0.0),
|
||
Speed = 0.0
|
||
};
|
||
string laserDecoyId = "LDY_1";
|
||
if (_threatSourceFactory.CreateJammer(laserDecoyId, "laser_decoy", motionParameters, "Tank_1") is LaserDecoy laserDecoy)
|
||
{
|
||
simulationManager.RegisterEntity(laserDecoyId, laserDecoy);
|
||
jammers[laserDecoyId] = laserDecoy as BaseJammer;
|
||
Console.WriteLine($"注册激光诱偏目标 {laserDecoyId}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 添加烟幕弹
|
||
/// </summary>
|
||
private void AddSmokeGrenade()
|
||
{
|
||
var motionParameters = new KinematicState
|
||
{
|
||
Position = new Vector3D(50, 5, 0),
|
||
Orientation = new Orientation(Math.PI/2, 0.0, 0.0),
|
||
Speed = 0.0
|
||
};
|
||
string smokeGrenadeId = "SG_1";
|
||
var smokeGrenade = _threatSourceFactory.CreateJammer(smokeGrenadeId, "surround", motionParameters, "Tank_1");
|
||
if (smokeGrenade is BaseJammer jammer1)
|
||
{
|
||
simulationManager.RegisterEntity(smokeGrenadeId, jammer1);
|
||
jammers[smokeGrenadeId] = jammer1;
|
||
Console.WriteLine($"注册烟幕弹 {smokeGrenadeId}");
|
||
}
|
||
|
||
smokeGrenadeId = "SG_2";
|
||
smokeGrenade = _threatSourceFactory.CreateJammer(smokeGrenadeId, "infrared", motionParameters, "Tank_1");
|
||
if (smokeGrenade is BaseJammer jammer2)
|
||
{
|
||
simulationManager.RegisterEntity(smokeGrenadeId, jammer2);
|
||
jammers[smokeGrenadeId] = jammer2;
|
||
Console.WriteLine($"注册烟幕弹 {smokeGrenadeId}");
|
||
}
|
||
|
||
smokeGrenadeId = "SG_3";
|
||
smokeGrenade = _threatSourceFactory.CreateJammer(smokeGrenadeId, "mmw", motionParameters, "Tank_1");
|
||
if (smokeGrenade is BaseJammer jammer3)
|
||
{
|
||
simulationManager.RegisterEntity(smokeGrenadeId, jammer3);
|
||
jammers[smokeGrenadeId] = jammer3;
|
||
Console.WriteLine($"注册烟幕弹 {smokeGrenadeId}");
|
||
}
|
||
|
||
var motionParametersTop = new KinematicState
|
||
{
|
||
Position = new Vector3D(0, 10, 0),
|
||
Orientation = new Orientation(0, Math.PI/2, 0.0),
|
||
Speed = 0.0
|
||
};
|
||
smokeGrenadeId = "SG_4";
|
||
smokeGrenade = _threatSourceFactory.CreateJammer(smokeGrenadeId, "top", motionParametersTop, "Tank_1");
|
||
if (smokeGrenade is BaseJammer jammer4)
|
||
{
|
||
simulationManager.RegisterEntity(smokeGrenadeId, jammer4);
|
||
jammers[smokeGrenadeId] = jammer4;
|
||
Console.WriteLine($"注册烟幕弹 {smokeGrenadeId}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 添加激光半主动制导导弹
|
||
/// </summary>
|
||
private void AddLaserSemiActiveMissile()
|
||
{
|
||
var motionParameters = new KinematicState
|
||
{
|
||
Position = new Vector3D(5000, 1, 10),
|
||
Orientation = new Orientation(Math.PI/2, Math.PI/20, 0),
|
||
Speed = 700
|
||
};
|
||
|
||
string missileId = "LSGM_1";
|
||
|
||
var missile = _threatSourceFactory.CreateMissile(missileId, "lsgm_001", "Tank_1", motionParameters);
|
||
missiles[missileId] = missile;
|
||
simulationManager.RegisterEntity(missileId, missile);
|
||
Console.WriteLine($"注册激光半主动制导导弹 {missileId},初始位置:{motionParameters.Position}");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 添加激光驾束制导导弹
|
||
/// </summary>
|
||
private void AddLaserBeamRiderMissile()
|
||
{
|
||
var motionParameters = new KinematicState
|
||
{
|
||
Position = new Vector3D(2000, 1, 10),
|
||
Orientation = new Orientation(Math.PI/2, 0.04, 0.0),
|
||
Speed = 10
|
||
};
|
||
|
||
string missileId = "LBRM_1";
|
||
|
||
var missile = _threatSourceFactory.CreateMissile(missileId, "hj10", "Tank_1", motionParameters);
|
||
missiles[missileId] = missile;
|
||
simulationManager.RegisterEntity(missileId, missile);
|
||
Console.WriteLine($"注册激光驾束制导导弹 {missileId},初始位置:{motionParameters.Position}");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 添加末敏弹
|
||
/// </summary>
|
||
private void AddTerminalSensitiveMissile()
|
||
{
|
||
var motionParameters = new KinematicState
|
||
{
|
||
Position = new Vector3D(3000, 1, 20),
|
||
Orientation = new Orientation(Math.PI/2, 0.0, 0.0),
|
||
Speed = 950
|
||
};
|
||
|
||
string missileId = "TSM_1";
|
||
|
||
var missile = _threatSourceFactory.CreateMissile(missileId, "tsm_001", "Tank_1", motionParameters);
|
||
missiles[missileId] = missile;
|
||
simulationManager.RegisterEntity(missileId, missile);
|
||
Console.WriteLine($"注册末敏弹 {missileId},初始位置:{motionParameters.Position}");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 添加红外指令制导导弹
|
||
/// </summary>
|
||
private void AddInfraredCommandMissile()
|
||
{
|
||
var motionParameters = new KinematicState
|
||
{
|
||
Position = new Vector3D(2000, 1, 20),
|
||
Orientation = new Orientation(Math.PI/2, 0.05, 0),
|
||
Speed = 10
|
||
};
|
||
|
||
string missileId = "ICGM_1";
|
||
|
||
var missile = _threatSourceFactory.CreateMissile(missileId, "irc_001", "Tank_1", motionParameters);
|
||
missiles[missileId] = missile;
|
||
simulationManager.RegisterEntity(missileId, missile);
|
||
Console.WriteLine($"注册红外指令制导导弹 {missileId},初始位置:{motionParameters.Position}");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 添加红外成像末制导导弹
|
||
/// </summary>
|
||
private void AddInfraredImagingMissile()
|
||
{
|
||
var motionParameters = new KinematicState
|
||
{
|
||
Position = new Vector3D(2000, 1, 0),
|
||
Orientation = new Orientation(Math.PI/2, Math.PI/15, 0),
|
||
Speed = 10
|
||
};
|
||
|
||
string missileId = "ITGM_1";
|
||
|
||
var missile = _threatSourceFactory.CreateMissile(missileId, "itg_001", "Tank_1", motionParameters);
|
||
missiles[missileId] = missile;
|
||
simulationManager.RegisterEntity(missileId, missile);
|
||
Console.WriteLine($"注册红外成像末制导导弹 {missileId},初始位置:{motionParameters.Position}");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 添加毫米波末制导导弹
|
||
/// </summary>
|
||
private void AddMillimeterWaveMissile()
|
||
{
|
||
var motionParameters = new KinematicState
|
||
{
|
||
Position = new Vector3D(2000, 1, 20),
|
||
Orientation = new Orientation(Math.PI/2, 0.05, 0),
|
||
Speed = 10
|
||
};
|
||
|
||
string missileId = "MMWG_1";
|
||
|
||
var missile = _threatSourceFactory.CreateMissile(missileId, "mmw_001", "Tank_1", motionParameters);
|
||
missiles[missileId] = missile;
|
||
simulationManager.RegisterEntity(missileId, missile);
|
||
Console.WriteLine($"注册毫米波末制导导弹 {missileId},初始位置:{motionParameters.Position}");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 添加复合制导导弹
|
||
/// </summary>
|
||
private void AddCompositeGuidanceMissile()
|
||
{
|
||
string missileId = "CGGM_1";
|
||
var motionParameters = new KinematicState
|
||
{
|
||
Position = new Vector3D(2000, 1, 20),
|
||
Orientation = new Orientation(Math.PI/2, 0.05, 0),
|
||
Speed = 10
|
||
};
|
||
|
||
var missile = _threatSourceFactory.CreateMissile(missileId, "cg_001", "Tank_1", motionParameters);
|
||
missiles[missileId] = missile;
|
||
simulationManager.RegisterEntity(missileId, missile);
|
||
Console.WriteLine($"注册毫米波/红外复合制导导弹 {missileId},初始位置:{motionParameters.Position}");
|
||
|
||
missileId = "CGGM_2";
|
||
motionParameters = new KinematicState
|
||
{
|
||
Position = new Vector3D(2000, 1, 20),
|
||
Orientation = new Orientation(Math.PI/2, 0.05, 0),
|
||
Speed = 10
|
||
};
|
||
|
||
missile = _threatSourceFactory.CreateMissile(missileId, "cg_002", "Tank_1", motionParameters);
|
||
missiles[missileId] = missile;
|
||
simulationManager.RegisterEntity(missileId, missile);
|
||
Console.WriteLine($"注册激光/红外复合制导导弹 {missileId},初始位置:{motionParameters.Position}");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 添加传感器和指示器
|
||
/// </summary>
|
||
private void AddIndicators()
|
||
{
|
||
// 添加激光目标指示器
|
||
string laserDesignatorId = "LD_1";
|
||
var laserDesignatorLaunchParams = new KinematicState
|
||
{
|
||
Position = new Vector3D(4000, 1, 100),
|
||
Orientation = new Orientation(Math.PI/2, 0.01, 0),
|
||
Speed = 0
|
||
};
|
||
var laserDesignator = _threatSourceFactory.CreateIndicator(laserDesignatorId, "ld_001", "Tank_1", "LSGM_1", laserDesignatorLaunchParams);
|
||
indicators[laserDesignatorId] = laserDesignator;
|
||
simulationManager.RegisterEntity(laserDesignatorId, laserDesignator);
|
||
Console.WriteLine($"注册激光目标指示器 {laserDesignatorId}");
|
||
|
||
// 添加激光驾束仪
|
||
string laserBeamRiderId = "LBR_1";
|
||
var laserBeamRiderLaunchParams = new KinematicState
|
||
{
|
||
Position = new Vector3D(2100, 1, 10),
|
||
Orientation = new Orientation(Math.PI/2, 0, 0),
|
||
Speed = 0
|
||
};
|
||
var laserBeamRider = _threatSourceFactory.CreateIndicator(laserBeamRiderId, "br_001", "Tank_1", "LBRM_1", laserBeamRiderLaunchParams);
|
||
indicators[laserBeamRiderId] = laserBeamRider;
|
||
simulationManager.RegisterEntity(laserBeamRiderId, laserBeamRider);
|
||
Console.WriteLine($"注册激光驾束仪 {laserBeamRiderId}");
|
||
|
||
// 添加红外测角仪
|
||
string infraredTrackerId = "IT_1";
|
||
var infraredTrackerLaunchParams = new KinematicState
|
||
{
|
||
Position = new Vector3D(2100, 1, 0),
|
||
Orientation = new Orientation(Math.PI/2, 0, 0),
|
||
Speed = 0
|
||
};
|
||
var infraredTracker = _threatSourceFactory.CreateIndicator(infraredTrackerId, "ir_001", "Tank_1", "ICGM_1", infraredTrackerLaunchParams);
|
||
indicators[infraredTrackerId] = infraredTracker;
|
||
simulationManager.RegisterEntity(infraredTrackerId, infraredTracker);
|
||
Console.WriteLine($"注册红外测角仪 {infraredTrackerId}");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 计算朝向实体的方向
|
||
/// </summary>
|
||
private Orientation CalculateOrientationToEntity(SimulationElement target)
|
||
{
|
||
// 使用CalculateDirectionToTarget获取归一化方向向量
|
||
Vector3D direction = target.KState.Position - new Vector3D(0, 0, 0);
|
||
|
||
// 创建朝向目标的方向
|
||
return Orientation.FromVector(direction.Normalize());
|
||
}
|
||
|
||
/// <summary>
|
||
/// 选择导弹
|
||
/// </summary>
|
||
/// <param name="missileId">导弹ID</param>
|
||
public void SelectMissile(string missileId)
|
||
{
|
||
Console.WriteLine($"=== 选择导弹: {missileId} ===");
|
||
|
||
// 新架构:完全销毁所有现有实体
|
||
DestroyAllEntities();
|
||
|
||
// 重新创建选中的导弹及其相关实体
|
||
CreateMissileAndRelatedEntities(missileId);
|
||
|
||
Console.WriteLine($"=== 导弹选择完成: {missileId} ===");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 激活与导弹相关的传感器、指示器、干扰器
|
||
/// </summary>
|
||
private void ActivateRelatedIndicators(string missileId)
|
||
{
|
||
// 根据导弹类型激活相应的传感器
|
||
switch (missileId)
|
||
{
|
||
case "LSGM_1": // 激光半主动制导导弹
|
||
if (indicators.TryGetValue("LD_1", out SimulationElement? value1))
|
||
{
|
||
value1.Activate();
|
||
}
|
||
Console.WriteLine($"干扰器数量 {jammers.Count}");
|
||
break;
|
||
case "LBRM_1": // 激光驾束制导导弹
|
||
if (indicators.TryGetValue("LBR_1", out SimulationElement? value2))
|
||
{
|
||
value2.Activate();
|
||
}
|
||
break;
|
||
case "ICGM_1": // 红外指令制导导弹
|
||
if (indicators.TryGetValue("IT_1", out SimulationElement? value3))
|
||
{
|
||
value3.Activate();
|
||
}
|
||
break;
|
||
case "CGGM_2": // 激光/红外复合制导导弹
|
||
if (indicators.TryGetValue("LD_1", out SimulationElement? value4))
|
||
{
|
||
value4.Activate();
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取当前选中导弹可用的干扰选项
|
||
/// </summary>
|
||
public (JammingType Type, string DisplayName, string JammerId, string Mode, string Target)[] GetAvailableJammingOptions()
|
||
{
|
||
if (string.IsNullOrEmpty(SelectedMissileId) || !missileJammingMap.ContainsKey(SelectedMissileId))
|
||
{
|
||
return [];
|
||
}
|
||
|
||
return missileJammingMap[SelectedMissileId].ToArray();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 应用干扰
|
||
/// </summary>
|
||
public void ApplyJamming(JammingType type, string displayName, string jammerId, string mode, string target)
|
||
{
|
||
// 检查并激活干扰器
|
||
if (jammers.ContainsKey(jammerId))
|
||
{
|
||
var jammerToActivate = jammers[jammerId];
|
||
jammerToActivate.Activate();
|
||
Console.WriteLine($"激活干扰器并开始干扰: {jammerId}: {displayName} (模式: {mode}, 作用: {target})");
|
||
|
||
// Add to activeJammings list if not already present
|
||
var jammingTuple = (Type: type, DisplayName: displayName, JammerId: jammerId, Mode: mode, Target: target);
|
||
if (!activeJammings.Any(j => j.JammerId == jammerId && j.Type == type)) // Simple check to avoid duplicates
|
||
{
|
||
activeJammings.Add(jammingTuple);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine($"警告:找不到干扰器 {jammerId}...");
|
||
PrintAllJammers();
|
||
}
|
||
|
||
// 根据干扰目标对象应用干扰
|
||
ApplyJammingToTargets(type, displayName, mode, target);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 打印所有注册的干扰器信息
|
||
/// </summary>
|
||
private void PrintAllJammers()
|
||
{
|
||
Console.WriteLine("\n所有注册的干扰器:");
|
||
if (jammers.Count == 0)
|
||
{
|
||
Console.WriteLine("没有任何干扰器被注册!");
|
||
return;
|
||
}
|
||
|
||
foreach (var jammer in jammers)
|
||
{
|
||
Console.WriteLine($"- {jammer.Key}: 类型={jammer.Value.GetType().Name}, 激活状态={jammer.Value.IsActive}");
|
||
if (jammer.Value.IsActive)
|
||
{
|
||
Console.WriteLine($" 状态: {jammer.Value.GetStatus()}");
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 根据目标类型应用干扰
|
||
/// </summary>
|
||
private void ApplyJammingToTargets(JammingType type, string displayName, string mode, string target)
|
||
{
|
||
// 根据target决定干扰作用对象
|
||
switch (target.ToLower())
|
||
{
|
||
case "指示器":
|
||
ApplyJammingToIndicators(type, mode);
|
||
break;
|
||
|
||
case "导弹":
|
||
ApplyJammingToMissiles(type, mode);
|
||
break;
|
||
|
||
case "两者":
|
||
ApplyJammingToIndicators(type, mode);
|
||
ApplyJammingToMissiles(type, mode);
|
||
break;
|
||
|
||
case "子弹药":
|
||
ApplyJammingToMissiles(type, mode);
|
||
break;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 应用干扰到指示器
|
||
/// </summary>
|
||
private void ApplyJammingToIndicators(JammingType type, string mode)
|
||
{
|
||
foreach (var indicator in indicators.Values.Where(i => i.IsActive))
|
||
{
|
||
Console.WriteLine($"应用{mode}干扰到指示器 {indicator.Id}");
|
||
try
|
||
{
|
||
// 根据干扰类型选择合适的干扰器ID
|
||
string jammerId = string.Empty;
|
||
switch (type)
|
||
{
|
||
case JammingType.Laser:
|
||
jammerId = "LaserJammer_Designator";
|
||
break;
|
||
case JammingType.Infrared:
|
||
jammerId = "InfraredJammer_Designator";
|
||
break;
|
||
case JammingType.MillimeterWave:
|
||
jammerId = "MillimeterWaveJammer_Missile"; // 假设这个也可以用于指示器
|
||
break;
|
||
case JammingType.SmokeGrenade:
|
||
if (indicator.Id.Contains("LD"))
|
||
jammerId = "SG_1"; // 激光烟幕
|
||
else if (indicator.Id.Contains("IR"))
|
||
jammerId = "SG_2"; // 红外烟幕
|
||
else
|
||
jammerId = "SG_3"; // 默认烟幕
|
||
break;
|
||
case JammingType.LaserDecoy:
|
||
jammerId = "LDY_1";
|
||
break;
|
||
}
|
||
|
||
if (!string.IsNullOrEmpty(jammerId) && jammers.ContainsKey(jammerId))
|
||
{
|
||
var jammer = jammers[jammerId];
|
||
|
||
// 创建干扰参数
|
||
JammingParameters jammingParams = new JammingParameters
|
||
{
|
||
Type = type,
|
||
Mode = mode.Equals("阻塞") ? JammingMode.Blocking :
|
||
mode.Equals("欺骗") ? JammingMode.Deception :
|
||
mode.Equals("噪声") ? JammingMode.Noise : JammingMode.Blocking,
|
||
JammerId = jammerId,
|
||
SourceId = jammer.Id,
|
||
Power = 800, // 设置合适功率
|
||
Direction = CalculateDirectionToTarget(jammer.KState.Position, indicator.KState.Position),
|
||
SourcePosition = jammer.KState.Position,
|
||
StartTime = DateTime.UtcNow,
|
||
Duration = 600 // 10分钟
|
||
};
|
||
|
||
// 找到指示器的实际实现类
|
||
if (indicator is IJammable jammableIndicator)
|
||
{
|
||
// 调用IJammable接口的ApplyJamming方法
|
||
jammableIndicator.ApplyJamming(jammingParams);
|
||
Console.WriteLine($"成功应用干扰到指示器 {indicator.Id},干扰源: {jammerId}");
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine($"警告: 指示器 {indicator.Id} 不支持IJammable接口");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine($"警告: 找不到合适的干扰器ID: {jammerId}");
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Console.WriteLine($"对指示器 {indicator.Id} 应用干扰时出错: {ex.Message}");
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 应用干扰到导弹
|
||
/// </summary>
|
||
private void ApplyJammingToMissiles(JammingType type, string mode)
|
||
{
|
||
foreach (var missile in missiles.Values.Where(m => m.IsActive))
|
||
{
|
||
Console.WriteLine($"应用{mode}干扰到导弹 {missile.Id}");
|
||
try
|
||
{
|
||
// 根据干扰类型和导弹类型选择合适的干扰器ID
|
||
string jammerId = string.Empty;
|
||
switch (type)
|
||
{
|
||
case JammingType.Laser:
|
||
jammerId = "LaserJammer_Missile";
|
||
break;
|
||
case JammingType.Infrared:
|
||
jammerId = "InfraredJammer_Missile";
|
||
break;
|
||
case JammingType.MillimeterWave:
|
||
if (missile.Id.Contains("TSM"))
|
||
jammerId = "MillimeterWaveJammer_Submunition"; // 针对子弹药
|
||
else
|
||
jammerId = "MillimeterWaveJammer_Missile";
|
||
break;
|
||
case JammingType.SmokeGrenade:
|
||
if (missile.Id.Contains("ITGM") || missile.Id.Contains("ICGM"))
|
||
jammerId = "SG_2"; // 红外烟幕用于红外导弹
|
||
else if (missile.Id.Contains("TSM"))
|
||
jammerId = "SG_3"; // 顶部烟幕用于子弹药
|
||
else
|
||
jammerId = "SG_1"; // 默认烟幕
|
||
break;
|
||
case JammingType.LaserDecoy:
|
||
jammerId = "LDY_1";
|
||
break;
|
||
}
|
||
|
||
if (!string.IsNullOrEmpty(jammerId) && jammers.ContainsKey(jammerId))
|
||
{
|
||
var jammer = jammers[jammerId];
|
||
|
||
// 创建干扰参数
|
||
JammingParameters jammingParams = new JammingParameters
|
||
{
|
||
Type = type,
|
||
Mode = mode.Equals("阻塞") ? JammingMode.Blocking :
|
||
mode.Equals("欺骗") ? JammingMode.Deception :
|
||
mode.Equals("噪声") ? JammingMode.Noise : JammingMode.Blocking,
|
||
JammerId = jammerId,
|
||
SourceId = jammer.Id,
|
||
Power = 1000, // 设置高功率
|
||
Direction = CalculateDirectionToTarget(jammer.KState.Position, missile.KState.Position),
|
||
SourcePosition = jammer.KState.Position,
|
||
StartTime = DateTime.UtcNow,
|
||
Duration = 600 // 10分钟
|
||
};
|
||
|
||
// 判断导弹是否实现了IJammable接口
|
||
if (missile is IJammable jammableMissile)
|
||
{
|
||
// 调用IJammable接口的ApplyJamming方法
|
||
jammableMissile.ApplyJamming(jammingParams);
|
||
Console.WriteLine($"成功应用干扰到导弹 {missile.Id},干扰源: {jammerId}");
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine($"警告: 导弹 {missile.Id} 不支持IJammable接口");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine($"警告: 找不到合适的干扰器ID: {jammerId}");
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Console.WriteLine($"对导弹 {missile.Id} 应用干扰时出错: {ex.Message}");
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 计算从源位置到目标位置的方向向量
|
||
/// </summary>
|
||
private Vector3D CalculateDirectionToTarget(Vector3D sourcePosition, Vector3D targetPosition)
|
||
{
|
||
Vector3D direction = targetPosition - sourcePosition;
|
||
return direction.Normalize();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 清除干扰
|
||
/// </summary>
|
||
public void ClearJamming(JammingType type, string displayName, string jammerId)
|
||
{
|
||
if (jammers.ContainsKey(jammerId))
|
||
{
|
||
jammers[jammerId].Deactivate();
|
||
Console.WriteLine($"关闭干扰器 {jammerId}: {displayName}");
|
||
|
||
// Remove from activeJammings list
|
||
activeJammings.RemoveAll(j => j.JammerId == jammerId && j.Type == type);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 应用干扰 (原有方法,保留向后兼容)
|
||
/// </summary>
|
||
public void ApplyJamming(JammingType type, string category)
|
||
{
|
||
switch (type)
|
||
{
|
||
case JammingType.SmokeGrenade:
|
||
if (category == "水平烟幕弹")
|
||
{
|
||
jammers["SG_1"].Activate();
|
||
}
|
||
else if (category == "红外烟幕弹")
|
||
{
|
||
jammers["SG_2"].Activate();
|
||
}
|
||
else if (category == "顶部烟幕弹")
|
||
{
|
||
jammers["SG_3"].Activate();
|
||
}
|
||
break;
|
||
case JammingType.LaserDecoy:
|
||
jammers["LDY_1"].Activate();
|
||
break;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 清除干扰 (原有方法,保留向后兼容)
|
||
/// </summary>
|
||
public void ClearJamming(JammingType type, string category)
|
||
{
|
||
var jammingParams = new JammingParameters
|
||
{
|
||
Type = type,
|
||
Power = 0,
|
||
Duration = 0,
|
||
Direction = new Vector3D(1, 0, 0),
|
||
SourcePosition = new Vector3D(0, 0, 0)
|
||
};
|
||
|
||
// 保留原有实现...
|
||
}
|
||
|
||
/// <summary>
|
||
/// 开始模拟
|
||
/// </summary>
|
||
public void Start()
|
||
{
|
||
Console.WriteLine("开始综合导弹模拟...");
|
||
|
||
// 使用新架构:销毁重建模式,确保每次都是全新的实体和位置
|
||
if (missiles.Count > 0 || targets.Count > 0)
|
||
{
|
||
Console.WriteLine("检测到现有实体,销毁并重新创建...");
|
||
|
||
// 保存当前选中的导弹ID和激活的干扰器列表,避免在销毁时被清空
|
||
string currentSelectedMissileId = SelectedMissileId;
|
||
var savedActiveJammings = activeJammings.ToList(); // 保存当前激活的干扰器列表
|
||
|
||
DestroyAllEntities();
|
||
|
||
// 重新创建选中的导弹及其相关实体
|
||
if (!string.IsNullOrEmpty(currentSelectedMissileId))
|
||
{
|
||
CreateMissileAndRelatedEntities(currentSelectedMissileId);
|
||
|
||
// 恢复用户选择的干扰器配置
|
||
if (savedActiveJammings.Count > 0)
|
||
{
|
||
Console.WriteLine($"恢复用户选择的 {savedActiveJammings.Count} 个干扰器配置...");
|
||
foreach (var jammingConfig in savedActiveJammings)
|
||
{
|
||
// 检查干扰器是否已创建
|
||
if (jammers.ContainsKey(jammingConfig.JammerId))
|
||
{
|
||
// 重新应用干扰配置
|
||
ApplyJamming(jammingConfig.Type, jammingConfig.DisplayName, jammingConfig.JammerId, jammingConfig.Mode, jammingConfig.Target);
|
||
Console.WriteLine($"已激活干扰器: {jammingConfig.DisplayName}");
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine("错误:没有选中的导弹");
|
||
return;
|
||
}
|
||
}
|
||
|
||
// 打印仿真开始前的组件状态
|
||
PrintSimulationRegisteredComponents();
|
||
|
||
// 启动仿真系统
|
||
simulationManager.StartSimulation(TimeStep);
|
||
|
||
while (simulationManager.State == SimulationState.Running)
|
||
{
|
||
// 让仿真管理器统一处理所有实体的更新
|
||
simulationManager.Update(TimeStep);
|
||
|
||
// 检查是否还有活跃的导弹
|
||
var activeMissiles = simulationManager.GetEntitiesByType<BaseMissile>()
|
||
.Where(m => m.IsActive);
|
||
|
||
if (!activeMissiles.Any())
|
||
{
|
||
simulationManager.StopSimulation();
|
||
SimulationEnded?.Invoke(this, EventArgs.Empty);
|
||
Console.WriteLine("仿真结束,所有导弹已完成任务");
|
||
break;
|
||
}
|
||
|
||
// 打印状态
|
||
PrintSimulationStatus();
|
||
|
||
Thread.Sleep((int)(TimeStep * 1000));
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 打印当前模拟状态
|
||
/// </summary>
|
||
private void PrintSimulationStatus()
|
||
{
|
||
// 获取当前仿真时间
|
||
double simulationTime = simulationManager.CurrentTime;
|
||
var weather = simulationManager.CurrentWeather;
|
||
|
||
Console.WriteLine($"\n========== 模拟状态 (时间: {simulationTime:F3}s)==========");
|
||
|
||
// 天气状态
|
||
Console.WriteLine("\n--- 天气环境 ---");
|
||
if (weather != null)
|
||
{
|
||
Console.WriteLine($"天气类型: {weather.Type}");
|
||
Console.WriteLine($"温度: {weather.Temperature:F1}°C, 湿度: {weather.RelativeHumidity:F1}%");
|
||
Console.WriteLine($"风速: {weather.WindSpeed:F1} m/s, 方向: ({weather.WindDirection:F1}°)");
|
||
Console.WriteLine($"雨量: {weather.Precipitation:F1} mm");
|
||
Console.WriteLine($"能见度: {weather.Visibility:F1} m");
|
||
}
|
||
|
||
// 导弹状态
|
||
Console.WriteLine("\n--- 导弹 ---");
|
||
var activeMissiles = simulationManager.GetEntitiesByType<BaseMissile>()
|
||
.Where(m => m.IsActive)
|
||
.ToList();
|
||
if (activeMissiles.Any())
|
||
{
|
||
foreach (var missile in activeMissiles)
|
||
{
|
||
// 直接调用导弹的GetStatus方法
|
||
Console.WriteLine(missile.GetStatus());
|
||
}
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine("没有激活的导弹");
|
||
}
|
||
|
||
// 目标状态
|
||
Console.WriteLine("\n--- 目标 ---");
|
||
var activeTargets = targets.Values.Where(t => t.IsActive).ToList();
|
||
if (activeTargets.Any())
|
||
{
|
||
foreach (var target in activeTargets)
|
||
{
|
||
// 调用目标的GetStatus方法
|
||
Console.WriteLine(target.GetStatus());
|
||
}
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine("没有激活的目标");
|
||
}
|
||
|
||
// 传感器状态
|
||
Console.WriteLine("\n--- 指示器 ---");
|
||
var activeIndicators = indicators.Values.Where(i => i.IsActive).ToList();
|
||
if (activeIndicators.Any())
|
||
{
|
||
foreach (var indicator in activeIndicators)
|
||
{
|
||
// 调用指示器的GetStatus方法
|
||
Console.WriteLine(indicator.GetStatus());
|
||
}
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine("没有激活的指示器");
|
||
}
|
||
|
||
// 干扰器状态
|
||
Console.WriteLine("\n--- 干扰器 ---");
|
||
var activeJammers = jammers.Values.Where(j => j.IsActive).ToList();
|
||
if (activeJammers.Any())
|
||
{
|
||
foreach (var jammer in activeJammers)
|
||
{
|
||
// 调用干扰器的GetStatus方法
|
||
Console.WriteLine(jammer.GetStatus());
|
||
|
||
// 如果正在干扰,显示更多详细信息
|
||
if (jammer.IsJamming)
|
||
{
|
||
try
|
||
{
|
||
var runningState = jammer.GetRunningState();
|
||
if (runningState.CurrentParameters != null)
|
||
{
|
||
var jammingParams = runningState.CurrentParameters;
|
||
|
||
// 计算已干扰时间和剩余时间
|
||
var jammingTimeSeconds = (DateTime.UtcNow.Ticks - jammingParams.StartTime.Ticks) / TimeSpan.TicksPerSecond;
|
||
Console.WriteLine($"- 已干扰时间: {jammingTimeSeconds:F1} 秒");
|
||
|
||
if (jammingParams.Duration.HasValue)
|
||
{
|
||
var remainingTime = jammingParams.Duration.Value - jammingTimeSeconds;
|
||
if (remainingTime > 0)
|
||
Console.WriteLine($"- 剩余时间: {remainingTime:F1} 秒");
|
||
else
|
||
Console.WriteLine("- 干扰即将结束");
|
||
}
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Console.WriteLine($" 获取干扰器详细状态出错: {ex.Message}");
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine("没有激活的干扰器");
|
||
}
|
||
|
||
Console.WriteLine("\n========================================");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 停止模拟
|
||
/// </summary>
|
||
public void Stop()
|
||
{
|
||
simulationManager.StopSimulation();
|
||
Console.WriteLine("模拟结束");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 暂停模拟
|
||
/// </summary>
|
||
public void Pause()
|
||
{
|
||
simulationManager.PauseSimulation();
|
||
Console.WriteLine("模拟暂停");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 恢复模拟
|
||
/// </summary>
|
||
public void Resume()
|
||
{
|
||
simulationManager.ResumeSimulation();
|
||
Console.WriteLine("模拟恢复");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 重置仿真状态
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// 新架构:由于采用销毁重建模式,此方法已简化
|
||
/// 主要功能已移至DestroyAllEntities和CreateMissileAndRelatedEntities方法
|
||
/// </remarks>
|
||
public void ResetSimulation()
|
||
{
|
||
Console.WriteLine("=== 开始重置仿真状态 ===");
|
||
|
||
// 停止仿真并清理事件系统
|
||
simulationManager.StopSimulation();
|
||
simulationManager.ClearAllEvents();
|
||
|
||
// 重置导弹激活状态
|
||
missileActiveStatus.Clear();
|
||
|
||
// 清理活跃干扰列表
|
||
activeJammings.Clear();
|
||
|
||
Console.WriteLine("=== 仿真状态重置完成 ===");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 打印所有注册到仿真管理器中的组件
|
||
/// </summary>
|
||
public void PrintSimulationRegisteredComponents()
|
||
{
|
||
Console.WriteLine("\n========== 仿真管理器中的注册组件 ==========");
|
||
var allEntities = simulationManager.GetAllEntities();
|
||
foreach (var entity in allEntities)
|
||
{
|
||
if (entity is SimulationElement simElement)
|
||
{
|
||
Console.WriteLine($"{simElement.Id} ({entity.GetType().Name})");
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine($"未知组件 ({entity.GetType().Name})");
|
||
}
|
||
}
|
||
Console.WriteLine($"总计: {allEntities.Count} 个组件");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取当前活动的传感器列表
|
||
/// </summary>
|
||
public (string Id, string Name, bool IsActive)[] GetActiveIndicators()
|
||
{
|
||
return indicators.Select(s => (
|
||
s.Value.Id,
|
||
GetIndicatorDisplayName(s.Value),
|
||
s.Value.IsActive
|
||
)).ToArray();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取传感器的显示名称
|
||
/// </summary>
|
||
private string GetIndicatorDisplayName(SimulationElement indicator)
|
||
{
|
||
return indicator switch
|
||
{
|
||
LaserDesignator _ => "激光目标指示器",
|
||
LaserBeamRider _ => "激光驾束仪",
|
||
InfraredTracker _ => "红外测角仪",
|
||
_ => indicator.Id
|
||
};
|
||
}
|
||
|
||
/// <summary>
|
||
/// 切换传感器的激活状态
|
||
/// </summary>
|
||
public void ToggleIndicator(string indicatorId)
|
||
{
|
||
if (indicators.TryGetValue(indicatorId, out var indicator))
|
||
{
|
||
if (indicator.IsActive)
|
||
indicator.Deactivate();
|
||
else
|
||
indicator.Activate();
|
||
|
||
Console.WriteLine($"指示器 {GetIndicatorDisplayName(indicator)} 已{(indicator.IsActive ? "激活" : "停用")}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 切换天气
|
||
/// </summary>
|
||
/// <param name="weatherType">天气类型</param>
|
||
public void SwitchWeather(string weatherType)
|
||
{
|
||
// 创建新的天气实例
|
||
var newWeather = _threatSourceFactory.CreateWeather(weatherType);
|
||
|
||
// 设置为当前天气
|
||
simulationManager.SetWeather(newWeather);
|
||
|
||
// 打印天气详情
|
||
Console.WriteLine($"已切换到 {weatherType} 天气环境");
|
||
Console.WriteLine($"温度: {newWeather.Temperature}°C");
|
||
Console.WriteLine($"湿度: {newWeather.RelativeHumidity}%");
|
||
Console.WriteLine($"能见度: {newWeather.Visibility}公里");
|
||
Console.WriteLine($"风速: {newWeather.WindSpeed}米/秒");
|
||
Console.WriteLine($"风向: {newWeather.WindDirection}°");
|
||
}
|
||
|
||
public string GetActiveJammingDescription()
|
||
{
|
||
if (activeJammings == null || activeJammings.Count == 0)
|
||
{
|
||
return "(无干扰)";
|
||
}
|
||
|
||
if (activeJammings.Count == 1)
|
||
{
|
||
return $"(已激活: {activeJammings.First().DisplayName})";
|
||
}
|
||
else
|
||
{
|
||
return $"(已激活: {activeJammings.Count}个干扰器)";
|
||
}
|
||
}
|
||
|
||
public List<(JammingType Type, string DisplayName, string JammerId, string Mode, string Target)> GetCurrentlyActiveJammings()
|
||
{
|
||
// 返回一个新的列表,防止外部修改内部列表
|
||
return [.. activeJammings];
|
||
}
|
||
|
||
/// <summary>
|
||
/// 销毁所有实体并从仿真管理器中注销
|
||
/// </summary>
|
||
/// <remarks>
|
||
/// 新架构:每次仿真结束后完全销毁所有实体,下次选择时重新创建
|
||
/// 这样可以避免状态残留问题,确保每次都是全新的实体
|
||
/// </remarks>
|
||
private void DestroyAllEntities()
|
||
{
|
||
Console.WriteLine("=== 开始销毁所有实体 ===");
|
||
|
||
// 停止仿真并清理事件系统
|
||
simulationManager.StopSimulation();
|
||
simulationManager.ClearAllEvents();
|
||
|
||
// 获取仿真管理器中所有注册的实体(包括动态生成的末敏弹子弹)
|
||
var allEntities = simulationManager.GetAllEntities();
|
||
Console.WriteLine($"发现 {allEntities.Count} 个实体需要清理");
|
||
|
||
// 逐个清理所有实体
|
||
foreach (var entity in allEntities)
|
||
{
|
||
if (entity is SimulationElement simElement)
|
||
{
|
||
simElement.Deactivate();
|
||
simulationManager.UnregisterEntity(simElement.Id);
|
||
Console.WriteLine($"销毁实体: {simElement.Id} ({entity.GetType().Name})");
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine($"跳过非SimulationElement实体: {entity.GetType().Name}");
|
||
}
|
||
}
|
||
|
||
// 清理本地字典
|
||
missiles.Clear();
|
||
targets.Clear();
|
||
indicators.Clear();
|
||
jammers.Clear();
|
||
|
||
// 清理状态
|
||
missileActiveStatus.Clear();
|
||
activeJammings.Clear();
|
||
SelectedMissileId = "";
|
||
|
||
Console.WriteLine("=== 所有实体销毁完成 ===");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 按需创建特定导弹及其相关实体
|
||
/// </summary>
|
||
/// <param name="missileId">要创建的导弹ID</param>
|
||
/// <remarks>
|
||
/// 新架构:每次选择导弹时重新创建所需的实体
|
||
/// 包括目标、导弹、指示器、干扰器等
|
||
/// </remarks>
|
||
private void CreateMissileAndRelatedEntities(string missileId)
|
||
{
|
||
Console.WriteLine($"=== 开始创建导弹 {missileId} 及相关实体 ===");
|
||
|
||
// 首先添加天气(如果还没有)
|
||
if (simulationManager.CurrentWeather == null)
|
||
{
|
||
AddWeathers();
|
||
}
|
||
|
||
// 创建目标
|
||
AddTankTarget();
|
||
|
||
// 根据导弹类型创建对应的导弹
|
||
switch (missileId)
|
||
{
|
||
case "LSGM_1":
|
||
AddLaserSemiActiveMissile();
|
||
break;
|
||
|
||
case "LBRM_1":
|
||
AddLaserBeamRiderMissile();
|
||
break;
|
||
|
||
case "TSM_1":
|
||
AddTerminalSensitiveMissile();
|
||
break;
|
||
|
||
case "ICGM_1":
|
||
AddInfraredCommandMissile();
|
||
break;
|
||
|
||
case "ITGM_1":
|
||
AddInfraredImagingMissile();
|
||
break;
|
||
|
||
case "MMWG_1":
|
||
AddMillimeterWaveMissile();
|
||
break;
|
||
|
||
case "CGGM_1":
|
||
case "CGGM_2":
|
||
AddCompositeGuidanceMissile(); // 这个方法会添加两种复合制导导弹
|
||
break;
|
||
|
||
default:
|
||
Console.WriteLine($"未知的导弹类型: {missileId}");
|
||
return;
|
||
}
|
||
|
||
// 添加所有指示器、干扰器和烟幕弹
|
||
AddIndicators();
|
||
|
||
// 根据导弹类型添加相应的干扰器
|
||
AddJammersForMissile(missileId);
|
||
|
||
// 添加烟幕弹和激光诱偏目标
|
||
AddSmokeGrenade();
|
||
AddLaserDecoy();
|
||
|
||
// 激活选中的导弹
|
||
if (missiles.TryGetValue(missileId, out var selectedMissile))
|
||
{
|
||
selectedMissile.Activate();
|
||
SelectedMissileId = missileId;
|
||
missileActiveStatus[missileId] = true;
|
||
Console.WriteLine($"已激活导弹: {missileId}");
|
||
|
||
// 激活相关指示器
|
||
ActivateRelatedIndicators(missileId);
|
||
}
|
||
|
||
Console.WriteLine($"=== 导弹 {missileId} 及相关实体创建完成 ===");
|
||
}
|
||
|
||
private void AddJammersForMissile(string missileId)
|
||
{
|
||
Console.WriteLine($"为导弹 {missileId} 创建相应的干扰器");
|
||
|
||
// 利用现有的导弹-干扰器映射
|
||
if (missileJammingMap.TryGetValue(missileId, out var jammingList))
|
||
{
|
||
foreach (var (type, displayName, jammerId, mode, target) in jammingList)
|
||
{
|
||
CreateJammerById(jammerId, type, target);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
Console.WriteLine($"未找到导弹 {missileId} 的干扰器映射");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 根据干扰器ID创建干扰器实体
|
||
/// </summary>
|
||
private void CreateJammerById(string jammerId, JammingType type, string target)
|
||
{
|
||
try
|
||
{
|
||
// 根据干扰器ID确定朝向
|
||
Orientation orientation = GetJammerOrientation(jammerId, target);
|
||
|
||
var jammerParams = new KinematicState
|
||
{
|
||
Position = new Vector3D(0, 0, 0),
|
||
Orientation = orientation,
|
||
Speed = 0.0
|
||
};
|
||
|
||
// 根据干扰器ID确定类型配置
|
||
string jammerConfig = GetJammerConfig(jammerId);
|
||
|
||
var jammer = _threatSourceFactory.CreateJammer(jammerId, jammerConfig, jammerParams, "Tank_1");
|
||
if (jammer is BaseJammer baseJammer)
|
||
{
|
||
simulationManager.RegisterEntity(jammerId, jammer);
|
||
jammers[jammerId] = baseJammer;
|
||
Console.WriteLine($"注册干扰器 {jammerId}");
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Console.WriteLine($"创建干扰器 {jammerId} 时出错: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 根据干扰器ID和目标确定朝向
|
||
/// </summary>
|
||
private Orientation GetJammerOrientation(string jammerId, string target)
|
||
{
|
||
// 根据干扰器ID和目标类型确定朝向
|
||
return jammerId switch
|
||
{
|
||
"LaserJammer_Designator" => GetOrientationToRelatedIndicator(), // 朝向与当前导弹相关的指示器
|
||
"LaserJammer_Missile" => GetOrientationToCurrentMissile(), // 朝向当前选中的导弹
|
||
"InfraredJammer_Designator" => GetOrientationToRelatedIndicator(), // 朝向与当前导弹相关的指示器
|
||
"InfraredJammer_Missile" => GetOrientationToCurrentMissile(), // 朝向当前选中的导弹
|
||
"MillimeterWaveJammer_Missile" => GetOrientationToCurrentMissile(), // 朝向当前选中的导弹
|
||
"LaserJammer_Submunition" or "InfraredJammer_Submunition" or "MillimeterWaveJammer_Submunition" or "MillimeterWaveCompensationJammer_Submunition"
|
||
=> new Orientation(0, Math.PI/2, 0), // 垂直向上
|
||
_ => new Orientation(0, 0, 0) // 默认朝向
|
||
};
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取朝向与当前选中导弹相关的指示器的方向
|
||
/// </summary>
|
||
private Orientation GetOrientationToRelatedIndicator()
|
||
{
|
||
// 根据当前选中的导弹确定相关的指示器
|
||
string[] relatedIndicatorIds = SelectedMissileId switch
|
||
{
|
||
"LSGM_1" => ["LD_1"], // 激光半主动导弹 -> 激光指示器
|
||
"LBRM_1" => ["LBR_1"], // 激光驾束导弹 -> 激光驾束仪
|
||
"ICGM_1" => ["IT_1"], // 红外指令导弹 -> 红外测角仪
|
||
"CGGM_2" => ["LD_1"], // 激光/红外复合导弹 -> 激光指示器
|
||
_ => ["LD_1", "LBR_1", "IT_1"] // 默认尝试所有指示器
|
||
};
|
||
|
||
return GetOrientationToIndicator(relatedIndicatorIds);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取朝向当前选中导弹的方向
|
||
/// </summary>
|
||
private Orientation GetOrientationToCurrentMissile()
|
||
{
|
||
if (!string.IsNullOrEmpty(SelectedMissileId) && missiles.TryGetValue(SelectedMissileId, out var missile))
|
||
{
|
||
return CalculateOrientationToEntity(missile);
|
||
}
|
||
return new Orientation(0, 0, 0); // 默认朝向
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取朝向指示器的方向
|
||
/// </summary>
|
||
private Orientation GetOrientationToIndicator(params string[] indicatorIds)
|
||
{
|
||
foreach (var indicatorId in indicatorIds)
|
||
{
|
||
if (indicators.TryGetValue(indicatorId, out var indicator))
|
||
{
|
||
return CalculateOrientationToEntity(indicator);
|
||
}
|
||
}
|
||
return new Orientation(0, 0, 0); // 默认朝向
|
||
}
|
||
|
||
/// <summary>
|
||
/// 根据干扰器ID确定配置类型
|
||
/// </summary>
|
||
private string GetJammerConfig(string jammerId)
|
||
{
|
||
return jammerId switch
|
||
{
|
||
"LaserJammer_Designator" or "LaserJammer_Missile" => "laser_blocking",
|
||
"LaserJammer_Submunition" => "laser_top_blocking",
|
||
"InfraredJammer_Designator" or "InfraredJammer_Missile" => "infrared_blocking",
|
||
"InfraredJammer_Submunition" => "infrared_top_blocking",
|
||
"MillimeterWaveJammer_Missile" or "MillimeterWaveJammer_Submunition" => "mmw_blocking",
|
||
"MillimeterWaveCompensationJammer_Submunition" => "mmw_compensation",
|
||
"LDY_1" => "laser_decoy",
|
||
"SG_1" => "surround",
|
||
"SG_2" => "infrared",
|
||
"SG_3" => "mmw",
|
||
"SG_4" => "top",
|
||
_ => "laser_blocking" // 默认配置
|
||
};
|
||
}
|
||
}
|
||
} |