对各模型进行了重构

This commit is contained in:
Tian jianyong 2024-10-09 00:37:27 +08:00
parent d9975acd3c
commit f36f00572c
12 changed files with 473 additions and 230 deletions

52
.cursorrules Normal file
View File

@ -0,0 +1,52 @@
您是 C#、Unity 和可扩展游戏开发的专家。
关键原则
- 编写清晰、技术性的响应,提供精确的 C# 和 Unity 示例。
- 尽可能使用 Unity 的内置功能和工具,以充分利用其能力。
- 优先考虑可读性和可维护性;遵循 C# 编码规范和 Unity 最佳实践。
- 使用描述性的变量和函数名称;遵循命名约定(例如,公共成员使用 PascalCase私有成员使用 camelCase
- 以模块化的方式构建项目,使用 Unity 的基于组件的架构,以促进可重用性和关注点分离。
C#/Unity
- 对于附加到 GameObject 的脚本组件,使用 MonoBehaviour对于数据容器和共享资源优先使用 ScriptableObjects。
- 利用 Unity 的物理引擎和碰撞检测系统来实现游戏机制和交互。
- 使用 Unity 的输入系统处理跨多个平台的玩家输入。
- 利用 Unity 的 UI 系统Canvas、UI 元素)创建用户界面。
- 严格遵循组件模式,以实现关注点的清晰分离和模块化。
- 在 Unity 的单线程环境中,使用协程处理基于时间的操作和异步任务。
错误处理和调试
- 在适当的地方使用 try-catch 块实现错误处理,特别是对于文件 I/O 和网络操作。
- 使用 Unity 的 Debug 类进行日志记录和调试例如Debug.Log、Debug.LogWarning、Debug.LogError
- 利用 Unity 的分析器和帧调试器识别和解决性能问题。
- 实现自定义错误消息和调试可视化,以改善开发体验。
- 使用 Unity 的断言系统Debug.Assert在开发过程中捕获逻辑错误。
依赖项
- Unity 引擎
- .NET 框架(与您的 Unity 版本兼容的版本)
- Unity 资产商店包(根据特定功能需要)
- 第三方插件(经过仔细审查以确保兼容性和性能)
Unity 特定指南
- 使用预制件Prefabs创建可重用的游戏对象和 UI 元素。
- 将游戏逻辑保留在脚本中;使用 Unity 编辑器进行场景组合和初始设置。
- 利用 Unity 的动画系统Animator、动画剪辑进行角色和对象动画。
- 应用 Unity 的内置光照和后处理效果以增强视觉效果。
- 使用 Unity 的内置测试框架进行单元测试和集成测试。
- 利用 Unity 的资源包系统进行高效的资源管理和加载。
- 使用 Unity 的标签和层系统进行对象分类和碰撞过滤。
性能优化
- 对于频繁实例化和销毁的对象,使用对象池。
- 通过批处理材质和使用精灵和 UI 元素的图集来优化绘制调用。
- 实现细节层次LOD系统以提高复杂 3D 模型的渲染性能。
- 使用 Unity 的作业系统和 Burst 编译器进行 CPU 密集型操作。
- 通过使用简化的碰撞网格和调整固定时间步长来优化物理性能。
关键约定
1. 遵循 Unity 的基于组件的架构,以实现模块化和可重用的游戏元素。
2. 在开发的每个阶段优先考虑性能优化和内存管理。
3. 维护清晰和逻辑的项目结构,以增强可读性和资产管理。
请参考 Unity 文档和 C# 编程指南,以获取脚本、游戏架构和性能优化的最佳实践。

View File

@ -6,54 +6,70 @@ namespace ActiveProtect.Models
public class LaserDesignator : SimulationElement
{
public string TargetId { get; private set; }
public bool IsActive { get; private set; }
public double JammingThreshold { get; private set; } = 0.0; // 将阈值调整为 0 dB
public double JammingThreshold { get; private set; } = 0.0; // 调整干扰阈值
public bool IsJammed { get; private set; } = false;
public double MaxIlluminationRange { get; private set; }
private bool IsIlluminating { get; set; } = false;
public LaserDesignator(string id, LaserDesignatorConfig config, ISimulationManager simulationManager)
public LaserDesignator(string id, string targetId, LaserDesignatorConfig config, ISimulationManager simulationManager)
: base(id, config.InitialPosition, new Orientation(), simulationManager)
{
TargetId = config.TargetId;
TargetId = targetId;
IsActive = true;
MaxIlluminationRange = config.MaxIlluminationRange;
simulationManager.SubscribeToEvent<LaserJammingEvent>(OnLaserJamming);
SimulationManager.SubscribeToEvent<LaserJammingEvent>(OnLaserJamming);
}
public override void Update(double deltaTime)
{
if (IsActive && !IsJammed)
{
IlluminateTarget();
UpdateIllumination();
}
else
else if (IsIlluminating)
{
StopIllumination();
}
}
private void IlluminateTarget()
private void UpdateIllumination()
{
if (SimulationManager.GetEntityById(TargetId) is ILaserIlluminatable target)
{
double distanceToTarget = Vector3D.Distance(Position, target.Position);
if (distanceToTarget <= MaxIlluminationRange)
{
target.Illuminate();
Console.WriteLine($"激光目标指示器 {Id} 正在照射目标 {TargetId}");
bool shouldIlluminate = distanceToTarget <= MaxIlluminationRange;
// 发布LaserIlluminationEvent
PublishEvent(new LaserIlluminationEvent
{
TargetId = TargetId
});
Console.WriteLine($"激光目标指示器 {Id} 状态更新:");
Console.WriteLine($" 目标: {TargetId}");
Console.WriteLine($" 距离目标: {distanceToTarget:F2} m (最大照射范围: {MaxIlluminationRange} m)");
Console.WriteLine($" 是否应该照射: {shouldIlluminate}");
Console.WriteLine($" 当前照射状态: {IsIlluminating}");
if (shouldIlluminate && !IsIlluminating)
{
StartIllumination(target);
}
else
else if (!shouldIlluminate && IsIlluminating)
{
StopIllumination();
Console.WriteLine($"激光目标指示器 {Id} 超出照射范围,停止照射目标 {TargetId}");
}
}
else
{
Console.WriteLine($"激光目标指示器 {Id} 无法找到目标 {TargetId}");
if (IsIlluminating)
{
StopIllumination();
}
}
}
private void StartIllumination(ILaserIlluminatable target)
{
target.Illuminate();
IsIlluminating = true;
Console.WriteLine($"激光目标指示器 {Id} 开始照射目标 {TargetId}");
PublishIlluminationEvent();
}
private void StopIllumination()
@ -61,22 +77,22 @@ namespace ActiveProtect.Models
if (SimulationManager.GetEntityById(TargetId) is ILaserIlluminatable target)
{
target.StopIllumination();
Console.WriteLine($"激光目标指示器 {Id} 停止照射目标 {TargetId}");
PublishIlluminationStopEvent();
}
IsIlluminating = false;
Console.WriteLine($"激光目标指示器 {Id} 停止照射目标 {TargetId}");
PublishIlluminationStopEvent();
}
private void OnLaserJamming(LaserJammingEvent evt)
{
if (evt.TargetId == TargetId)
{
if (SimulationManager.GetEntityById(TargetId) is Tank target)
var tank = SimulationManager.GetEntityById(TargetId) as Tank;
if (tank != null)
{
double distanceToTarget = Vector3D.Distance(Position, target.Position);
// 调整干扰效果计算方法
double distanceToTarget = Vector3D.Distance(Position, tank.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)
@ -85,7 +101,7 @@ namespace ActiveProtect.Models
{
Console.WriteLine($"激光目标指示器 {Id} 被干扰,停止工作");
IsJammed = true;
DeactivateLaser();
StopIllumination();
}
}
else
@ -94,7 +110,6 @@ namespace ActiveProtect.Models
{
Console.WriteLine($"激光目标指示器 {Id} 干扰解除,恢复工作");
IsJammed = false;
ActivateLaser();
}
}
}
@ -106,7 +121,7 @@ namespace ActiveProtect.Models
IsActive = true;
IsJammed = false;
Console.WriteLine($"激光目标指示器 {Id} 已激活");
IlluminateTarget(); // 立即开始照射目标
UpdateIllumination();
}
public void DeactivateLaser()
@ -119,6 +134,14 @@ namespace ActiveProtect.Models
}
}
private void PublishIlluminationEvent()
{
PublishEvent(new LaserIlluminationEvent
{
TargetId = TargetId
});
}
private void PublishIlluminationStopEvent()
{
PublishEvent(new LaserIlluminationStopEvent
@ -133,6 +156,7 @@ namespace ActiveProtect.Models
$" 位置: {Position}\n" +
$" 目标: {TargetId}\n" +
$" 激活状态: {(IsActive ? "" : "")}\n" +
$" 照射状态: {(IsIlluminating ? "" : "")}\n" +
$" 干扰状态: {(IsJammed ? "" : "")}\n" +
$" 最大照射范围: {MaxIlluminationRange}";
}

View File

@ -3,52 +3,90 @@ using ActiveProtect.SimulationEnvironment;
namespace ActiveProtect.Models
{
public class LaserJammer
public class LaserJammer : SimulationElement
{
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; // 每秒增加的功率
private readonly double maxJammingCooldown;
private readonly double maxJammingPower;
private readonly double initialJammingPower;
private readonly double powerIncreaseRate;
public string MonitoredEntityId { get; private set; }
public LaserJammer(Tank tank)
public LaserJammer(string id, Vector3D position, Orientation orientation, ISimulationManager simulationManager, string monitoredEntityId, LaserJammerConfig config)
: base(id, position, orientation, simulationManager)
{
this.tank = tank;
MonitoredEntityId = monitoredEntityId;
IsJamming = false;
JammingPower = 0;
tank.SimulationManager.SubscribeToEvent<LaserIlluminationStopEvent>(OnLaserIlluminationStop);
maxJammingCooldown = config.MaxJammingCooldown;
maxJammingPower = config.MaxJammingPower;
initialJammingPower = config.InitialJammingPower;
powerIncreaseRate = config.PowerIncreaseRate;
SimulationManager.SubscribeToEvent<LaserIlluminationEvent>(OnLaserIllumination);
SimulationManager.SubscribeToEvent<LaserIlluminationStopEvent>(OnLaserIlluminationStop);
}
public void Update(double deltaTime)
public override void Update(double deltaTime)
{
if (!IsActive) return;
var tank = SimulationManager.GetEntityById(MonitoredEntityId) as Tank;
if (tank != null)
{
Position = tank.Position;
Orientation = tank.Orientation;
}
if (IsJamming)
{
// 逐渐增加干扰功率
JammingPower = Math.Min(JammingPower + PowerIncreaseRate * deltaTime, MaxJammingPower);
JammingPower = Math.Min(JammingPower + powerIncreaseRate * deltaTime, maxJammingPower);
jammingCooldown += deltaTime;
if (jammingCooldown >= MaxJammingCooldown)
if (jammingCooldown >= maxJammingCooldown)
{
StopJamming();
}
else
{
// 发布干扰事件
PublishEvent(new LaserJammingEvent
{
TargetId = MonitoredEntityId,
JammingPower = JammingPower
});
}
Console.WriteLine($"坦克 {tank.Id} 的激光干扰器正在工作,当前功率: {JammingPower:F2}");
Console.WriteLine($"激光干扰器 {Id} 正在工作,当前功率: {JammingPower:F2}");
}
else if (tank.LaserWarner.IsAlarming)
}
private void OnLaserIllumination(LaserIlluminationEvent evt)
{
if (evt.TargetId == MonitoredEntityId)
{
StartJamming();
}
}
private void OnLaserIlluminationStop(LaserIlluminationStopEvent evt)
{
if (evt.TargetId == MonitoredEntityId)
{
StopJamming();
}
}
private void StartJamming()
{
IsJamming = true;
JammingPower = InitialJammingPower; // 从初始功率开始
jammingCooldown = 0;
Console.WriteLine($"坦克 {tank.Id} 的激光干扰器开始工作,初始功率: {JammingPower:F2}");
if (!IsJamming)
{
IsJamming = true;
JammingPower = initialJammingPower;
jammingCooldown = 0;
Console.WriteLine($"激光干扰器 {Id} 开始工作,初始功率: {JammingPower:F2}");
}
}
private void StopJamming()
@ -58,17 +96,24 @@ namespace ActiveProtect.Models
IsJamming = false;
JammingPower = 0;
jammingCooldown = 0;
Console.WriteLine($"坦克 {tank.Id} 的激光干扰器停止工作");
Console.WriteLine($"激光干扰器 {Id} 停止工作");
}
}
private void OnLaserIlluminationStop(LaserIlluminationStopEvent evt)
public override string GetStatus()
{
if (evt.TargetId == tank.Id)
{
Console.WriteLine($"坦克 {tank.Id} 接收到激光照射停止事件,停止干扰");
StopJamming();
}
return $"激光干扰器 {Id}:\n" +
$" 监视实体: {MonitoredEntityId}\n" +
$" 干扰状态: {(IsJamming ? "" : "")}\n" +
$" 当前功率: {JammingPower:F2}/{maxJammingPower:F2}\n" +
$" 冷却时间: {jammingCooldown:F2}/{maxJammingCooldown:F2}";
}
protected override void Deactivate()
{
base.Deactivate();
SimulationManager.UnsubscribeFromEvent<LaserIlluminationEvent>(OnLaserIllumination);
SimulationManager.UnsubscribeFromEvent<LaserIlluminationStopEvent>(OnLaserIlluminationStop);
}
}
}

View File

@ -5,9 +5,7 @@ namespace ActiveProtect.Models
{
public class LaserSemiActiveGuidedMissile : Missile
{
public bool IsLaserDetected { get; private set; } = false;
public bool IsLaserLocked { get; private set; } = false;
private const double LaserLockDistance = 1000; // 1公里单位
private const double LaserLockDistance = 2000; // 1公里单位
public LaserSemiActiveGuidedMissile(
string id,
@ -16,68 +14,67 @@ namespace ActiveProtect.Models
: base(id, missileConfig, simulationManager)
{
Type = MissileType.SemiActiveLaserGuidance;
simulationManager.SubscribeToEvent<LaserIlluminationEvent>(OnLaserIllumination);
simulationManager.SubscribeToEvent<LaserIlluminationStopEvent>(OnLaserIlluminationStop);
}
public override void Update(double deltaTime)
{
base.Update(deltaTime);
UpdateLaserDetection();
if (IsLaserDetected)
UpdateGuidanceStatus();
}
private void UpdateGuidanceStatus()
{
if (SimulationManager.GetEntityById(TargetId) is ILaserIlluminatable target)
{
UpdateLaserLock();
IsGuidanceLost = false;
bool isIlluminated = target.IsIlluminated;
bool isWithinRange = DistanceToTarget <= LaserLockDistance;
HasGuidance = isIlluminated && isWithinRange;
Console.WriteLine($"激光半主动制导导弹 {Id} 状态更新:");
Console.WriteLine($" 目标 {TargetId} 是否被照射: {isIlluminated}");
Console.WriteLine($" 距离目标: {DistanceToTarget:F2} m (最大锁定距离: {LaserLockDistance} m)");
Console.WriteLine($" 是否在锁定范围内: {isWithinRange}");
Console.WriteLine($" 引导状态: {(HasGuidance ? "" : "")}");
}
else
{
LoseGuidance();
HasGuidance = false;
Console.WriteLine($"激光半主动制导导弹 {Id} 无法找到目标 {TargetId}");
}
}
private void UpdateLaserDetection()
private void OnLaserIllumination(LaserIlluminationEvent evt)
{
var target = SimulationManager.GetEntityById(TargetId) as ILaserIlluminatable;
if (target != null)
if (evt.TargetId == TargetId)
{
IsLaserDetected = target.IsIlluminated && DistanceToTarget <= LaserLockDistance;
}
else
{
IsLaserDetected = false;
Console.WriteLine($"激光半主动制导导弹 {Id} 检测到目标 {TargetId} 被激光照射");
UpdateGuidanceStatus();
}
}
private void UpdateLaserLock()
private void OnLaserIlluminationStop(LaserIlluminationStopEvent evt)
{
IsLaserLocked = IsLaserDetected;
if (IsLaserLocked)
if (evt.TargetId == TargetId)
{
AdjustTrajectoryBasedOnLaserGuidance();
}
}
private void AdjustTrajectoryBasedOnLaserGuidance()
{
// 实现基于激光导引的轨迹调整
// 这里可以添加更精确的导引逻辑
}
protected override void LoseGuidance()
{
if (!IsLaserDetected)
{
base.LoseGuidance();
IsLaserLocked = false;
Console.WriteLine($"激光半主动制导导弹 {Id} 失去激光引导");
Console.WriteLine($"激光半主动制导导弹 {Id} 检测到目标 {TargetId} 激光照射停止");
UpdateGuidanceStatus();
}
}
public override string GetStatus()
{
string baseStatus = base.GetStatus().Replace("导弹", "激光半主动制导导弹");
string additionalStatus = $"\n 激光检测: {(IsLaserDetected ? "" : "")}" +
$"\n 激光锁定: {(IsLaserLocked ? "" : "")}";
string additionalStatus = $"\n 激光引导: {(HasGuidance ? "" : "")}";
return baseStatus + additionalStatus;
}
protected override void Deactivate()
{
base.Deactivate();
SimulationManager.UnsubscribeFromEvent<LaserIlluminationEvent>(OnLaserIllumination);
SimulationManager.UnsubscribeFromEvent<LaserIlluminationStopEvent>(OnLaserIlluminationStop);
}
}
}
}

View File

@ -3,23 +3,34 @@ using System;
namespace ActiveProtect.Models
{
public class LaserWarner
public class LaserWarner : SimulationElement
{
private readonly Tank tank;
public bool IsAlarming { get; private set; }
private double alarmDuration = 5.0; // 警报持续5秒
private readonly double alarmDuration;
private double alarmTimer = 0;
public string MonitoredEntityId { get; private set; }
public LaserWarner(Tank tank)
public LaserWarner(string id, Vector3D position, Orientation orientation, ISimulationManager simulationManager, string monitoredEntityId, LaserWarnerConfig config)
: base(id, position, orientation, simulationManager)
{
this.tank = tank;
MonitoredEntityId = monitoredEntityId;
IsAlarming = false;
tank.SimulationManager.SubscribeToEvent<LaserIlluminationEvent>(OnLaserIllumination);
tank.SimulationManager.SubscribeToEvent<LaserIlluminationStopEvent>(OnLaserIlluminationStop);
alarmDuration = config.AlarmDuration;
SimulationManager.SubscribeToEvent<LaserIlluminationEvent>(OnLaserIllumination);
SimulationManager.SubscribeToEvent<LaserIlluminationStopEvent>(OnLaserIlluminationStop);
}
public void Update(double deltaTime)
public override void Update(double deltaTime)
{
if (!IsActive) return;
var tank = SimulationManager.GetEntityById(MonitoredEntityId) as Tank;
if (tank != null)
{
Position = tank.Position;
Orientation = tank.Orientation;
}
if (IsAlarming)
{
alarmTimer += deltaTime;
@ -32,7 +43,7 @@ namespace ActiveProtect.Models
private void OnLaserIllumination(LaserIlluminationEvent evt)
{
if (evt.TargetId == tank.Id)
if (evt.TargetId == MonitoredEntityId)
{
TriggerAlarm();
}
@ -40,7 +51,7 @@ namespace ActiveProtect.Models
private void OnLaserIlluminationStop(LaserIlluminationStopEvent evt)
{
if (evt.TargetId == tank.Id)
if (evt.TargetId == MonitoredEntityId)
{
StopAlarm();
}
@ -52,7 +63,7 @@ namespace ActiveProtect.Models
{
IsAlarming = true;
alarmTimer = 0;
Console.WriteLine($"坦克 {tank.Id} 的激光告警器发出警报!");
Console.WriteLine($"激光告警器 {Id} 发出警报!");
}
}
@ -62,8 +73,23 @@ namespace ActiveProtect.Models
{
IsAlarming = false;
alarmTimer = 0;
Console.WriteLine($"坦克 {tank.Id} 的激光告警器停止警报");
Console.WriteLine($"激光告警器 {Id} 停止警报");
}
}
public override string GetStatus()
{
return $"激光告警器 {Id}:\n" +
$" 监视实体: {MonitoredEntityId}\n" +
$" 警报状态: {(IsAlarming ? "" : "")}\n" +
$" 警报持续时间: {(IsAlarming ? alarmTimer : 0):F2}/{alarmDuration:F2}";
}
protected override void Deactivate()
{
base.Deactivate();
SimulationManager.UnsubscribeFromEvent<LaserIlluminationEvent>(OnLaserIllumination);
SimulationManager.UnsubscribeFromEvent<LaserIlluminationStopEvent>(OnLaserIlluminationStop);
}
}
}

View File

@ -39,7 +39,6 @@ namespace ActiveProtect.Models
public MissileDistanceParams DistanceParams { get; protected set; }
public FlightStageConfig StageConfig { get; protected set; }
public FlightStage CurrentStage { get; protected set; }
public bool IsActive { get; protected set; }
protected Vector3D Velocity;
private Vector3D LastTargetPosition;
@ -53,7 +52,7 @@ namespace ActiveProtect.Models
public double ProportionalNavigationCoefficient { get; set; }
public bool IsGuidanceLost { get; protected set; } = false;
public bool HasGuidance { get; protected set; } = true;
protected double LostGuidanceTime { get; set; } = 0;
protected const double MaxLostGuidanceTime = 1.0; // 1秒后自毁
@ -90,15 +89,19 @@ namespace ActiveProtect.Models
LastTargetPosition = Position; // 初始化 LastTargetPosition
// 订阅相关事件
simulationManager.SubscribeToEvent<LaserIlluminationEvent>(OnLaserIllumination);
simulationManager.SubscribeToEvent<LaserIlluminationStopEvent>(OnLaserIlluminationStop);
}
public override void Update(double deltaTime)
{
if (!IsActive) return;
// 首先检查是否应该自毁
if (ShouldSelfDestruct())
{
SelfDestruct();
return;
}
// 更新发动机燃烧时间
UpdateEngineBurnTime(deltaTime);
@ -125,33 +128,24 @@ namespace ActiveProtect.Models
Orientation = Orientation.FromVector(Velocity);
FlightTime += deltaTime;
FlightDistance += Speed * deltaTime;
DistanceToTarget = Vector3D.Distance(Position, SimulationManager.GetEntityById(TargetId).Position);
UpdateDistanceToTarget(Vector3D.Distance(Position, SimulationManager.GetEntityById(TargetId).Position));
// 首先检查是否命中目标
// 检查是否命中目标
if (CheckHit())
{
Explode();
return;
}
// 然后检查是否应该自毁
if (ShouldSelfDestruct())
{
SelfDestruct();
return;
}
// 更新飞行阶段
UpdateFlightStage();
if (IsGuidanceLost)
if (!HasGuidance)
{
HandleLostGuidance(deltaTime);
}
else
{
// 重置失去引导的时间
LostGuidanceTime = 0;
}
@ -169,7 +163,22 @@ namespace ActiveProtect.Models
private bool ShouldSelfDestruct()
{
return FlightTime >= MaxFlightTime || FlightDistance >= MaxFlightDistance || Position.Y <= 0;
if (FlightTime >= MaxFlightTime)
{
Console.WriteLine($"导弹 {Id} 超出最大飞行时间 ({FlightTime:F2}/{MaxFlightTime:F2}),准备自毁");
return true;
}
if (FlightDistance >= MaxFlightDistance)
{
Console.WriteLine($"导弹 {Id} 超出最大飞行距离 ({FlightDistance:F2}/{MaxFlightDistance:F2}),准备自毁");
return true;
}
if (Position.Y <= 0)
{
Console.WriteLine($"导弹 {Id} 高度小于等于0 ({Position.Y:F2}),准备自毁");
return true;
}
return false;
}
private void UpdateEngineBurnTime(double deltaTime)
@ -248,27 +257,25 @@ namespace ActiveProtect.Models
}
}
public void UpdateDistanceToTarget(double distance)
{
DistanceToTarget = distance;
}
public void Explode()
{
IsActive = false;
Deactivate();
SimulationManager.HandleTargetHit(TargetId, Id);
Console.WriteLine($"导弹 {Id} 在 {Position} 爆炸,命中目标!");
}
public void SelfDestruct()
{
IsActive = false;
string reason = FlightTime >= MaxFlightTime ? "超出最大飞行时间" :
FlightDistance >= MaxFlightDistance ? "超出最大飞行距" :
Position.Y <= 0 ? "高度小于等于0" :
IsGuidanceLost ? "失去引导" : "未知原因";
Console.WriteLine($"导弹 {Id} 自毁。原因: {reason}");
if (IsActive)
{
string reason = FlightTime >= MaxFlightTime ? "超出最大飞行时间" :
FlightDistance >= MaxFlightDistance ? "超出最大飞行距离" :
Position.Y <= 0 ? "高度小于等于0" :
!HasGuidance ? "失去引导" : "未知原因";
Console.WriteLine($"导弹 {Id} 自毁。原因: {reason}");
Deactivate();
}
}
public override string GetStatus()
@ -281,7 +288,7 @@ namespace ActiveProtect.Models
$" 飞行距离: {FlightDistance:F2}/{MaxFlightDistance:F2}\n" +
$" 距离目标: {DistanceToTarget:F2}\n" +
$" 发动机工作时间: {EngineBurnTime:F2}/{MaxEngineBurnTime:F2}\n" +
$" 失去引导: {(IsGuidanceLost ? "" : "")}\n" +
$" 有引导: {(HasGuidance ? "" : "")}\n" +
$" 失去引导时间: {LostGuidanceTime:F2}/{MaxLostGuidanceTime:F2}";
}
@ -291,15 +298,6 @@ namespace ActiveProtect.Models
Console.WriteLine($"导弹 {Id} 的比例导引系数已更新为 {newCoefficient}");
}
protected virtual void LoseGuidance()
{
if (!IsGuidanceLost)
{
Console.WriteLine($"导弹 {Id} 失去引导");
IsGuidanceLost = true;
}
}
protected virtual void HandleLostGuidance(double deltaTime)
{
LostGuidanceTime += deltaTime;
@ -310,33 +308,6 @@ namespace ActiveProtect.Models
}
}
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;
}
}
}
}

View File

@ -6,13 +6,10 @@ namespace ActiveProtect.Models
public class Tank : SimulationElement, ILaserIlluminatable
{
public double Speed { get; 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)
@ -21,10 +18,6 @@ namespace ActiveProtect.Models
MaxSpeed = tankConfig.MaxSpeed;
MaxArmor = tankConfig.MaxArmor;
CurrentArmor = tankConfig.MaxArmor;
LaserWarner = new LaserWarner(this);
LaserJammer = new LaserJammer(this);
// 移除事件订阅因为现在由LaserWarner直接处理
}
public override void Update(double deltaTime)
@ -32,18 +25,7 @@ namespace ActiveProtect.Models
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)
@ -63,23 +45,28 @@ namespace ActiveProtect.Models
CurrentArmor = Math.Max(0, CurrentArmor - damage);
if (CurrentArmor <= 0)
{
IsActive = false;
PublishEvent(new EntityDestroyedEvent { DestroyedEntityId = Id });
Deactivate();
}
}
public void Illuminate()
{
IsIlluminated = true;
if (!IsIlluminated)
{
IsIlluminated = true;
Console.WriteLine($"坦克 {Id} 被激光照射");
}
}
public void StopIllumination()
{
IsIlluminated = false;
if (IsIlluminated)
{
IsIlluminated = false;
Console.WriteLine($"坦克 {Id} 激光照射停止");
}
}
// 移除OnLaserIllumination和OnLaserIlluminationStop方法因为现在由LaserWarner直接处理
public override string GetStatus()
{
return $"坦克 {Id}:\n" +
@ -87,9 +74,7 @@ namespace ActiveProtect.Models
$" 速度: {Speed:F2}/{MaxSpeed:F2}\n" +
$" 装甲: {CurrentArmor:F2}/{MaxArmor:F2}\n" +
$" 状态: {(IsActive ? "" : "")}\n" +
$" 激光照射: {(IsIlluminated ? "" : "")}\n" +
$" 激光报警: {(LaserWarner.IsAlarming ? "" : "")}\n" +
$" 激光干扰: {(LaserJammer.IsJamming ? $" (: {LaserJammer.JammingPower:F2})" : "")}";
$" 激光照射: {(IsIlluminated ? "" : "")}\n";
}
}
}

View File

@ -19,9 +19,22 @@ namespace ActiveProtect
InitialOrientation = new Orientation(0, 0, 0),
InitialSpeed = 0,
MaxSpeed = 20,
MaxArmor = 100
MaxArmor = 100,
HasLaserWarner = true,
HasLaserJammer = true
}
],
LaserWarnerConfig = new LaserWarnerConfig
{
AlarmDuration = 5.0
},
LaserJammerConfig = new LaserJammerConfig
{
MaxJammingCooldown = 5.0,
MaxJammingPower = 10000.0,
InitialJammingPower = 4000.0,
PowerIncreaseRate = 2000.0
},
MissileConfigs =
[
// 标准导弹配置
@ -31,7 +44,7 @@ namespace ActiveProtect
InitialSpeed = 10,
MaxSpeed = 400,
TargetIndex = 0,
MaxFlightTime = 0,
MaxFlightTime = 0.5,
MaxFlightDistance = 5000,
ThrustAcceleration = 80,
MaxEngineBurnTime = 5,
@ -48,7 +61,7 @@ namespace ActiveProtect
InitialSpeed = 700,
MaxSpeed = 800,
TargetIndex = 0,
MaxFlightTime = 0,
MaxFlightTime = 0.5,
MaxFlightDistance = 5000,
ThrustAcceleration = 50,
MaxEngineBurnTime = 5,
@ -65,7 +78,7 @@ namespace ActiveProtect
InitialSpeed = 10,
MaxSpeed = 300,
TargetIndex = 0,
MaxFlightTime = 0,
MaxFlightTime = 0.5,
MaxFlightDistance = 3000,
ThrustAcceleration = 50,
MaxEngineBurnTime = 5,
@ -82,7 +95,7 @@ namespace ActiveProtect
InitialSpeed = 700,
MaxSpeed = 800,
TargetIndex = 0,
MaxFlightTime = 20,
MaxFlightTime = 5,
MaxFlightDistance = 4500,
ThrustAcceleration = 50,
MaxEngineBurnTime = 5,
@ -98,7 +111,6 @@ namespace ActiveProtect
new LaserDesignatorConfig
{
InitialPosition = new Vector3D(500, 150, 100),
TargetId = "Tank_1",
MaxIlluminationRange = 1000
}
],
@ -109,7 +121,7 @@ namespace ActiveProtect
var simulationManager = new SimulationManager(config);
// 运行仿真
int maxIterations = 1000; // 增加最大迭代次数
int maxIterations = 1000;
int iteration = 0;
while (!simulationManager.IsSimulationEnded && iteration < maxIterations)
{
@ -121,6 +133,5 @@ namespace ActiveProtect
Console.WriteLine("仿真结束");
}
}
}

View File

@ -7,6 +7,8 @@ namespace ActiveProtect.SimulationEnvironment
public List<TankConfig> TankConfigs { get; set; }
public List<MissileConfig> MissileConfigs { get; set; }
public List<LaserDesignatorConfig> LaserDesignatorConfigs { get; set; }
public LaserWarnerConfig LaserWarnerConfig { get; set; }
public LaserJammerConfig LaserJammerConfig { get; set; }
public double SimulationTimeStep { get; set; }
public SimulationConfig()
@ -14,6 +16,8 @@ namespace ActiveProtect.SimulationEnvironment
TankConfigs = [];
MissileConfigs = [];
LaserDesignatorConfigs = [];
LaserWarnerConfig = new LaserWarnerConfig();
LaserJammerConfig = new LaserJammerConfig();
SimulationTimeStep = 0.1; // 默认时间步长为0.1秒
}
}
@ -26,6 +30,9 @@ namespace ActiveProtect.SimulationEnvironment
public double MaxSpeed { get; set; }
public double MaxArmor { get; set; }
public bool HasLaserWarner { get; set; }
public bool HasLaserJammer { get; set; }
public TankConfig()
{
InitialPosition = new Vector3D(0, 0, 0);
@ -53,7 +60,7 @@ namespace ActiveProtect.SimulationEnvironment
public MissileConfig()
{
InitialPosition = new Vector3D(0, 0, 0); // 初始位<EFBFBD><EFBFBD>
InitialPosition = new Vector3D(0, 0, 0); // 初始位
InitialOrientation = new Orientation(0, 0, 0); // 初始方向
InitialSpeed = 0; // 初始速度
MaxSpeed = 0; // 最大速度
@ -73,12 +80,10 @@ namespace ActiveProtect.SimulationEnvironment
public class LaserDesignatorConfig
{
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;
}
}
@ -125,4 +130,31 @@ namespace ActiveProtect.SimulationEnvironment
/// </summary>
public static FlightStageConfig LaserSemiActiveGuidedMissile => new(enableAcceleration: false);
}
}
public class LaserWarnerConfig
{
public double AlarmDuration { get; set; }
public LaserWarnerConfig()
{
AlarmDuration = 5.0; // 默认警报持续5秒
}
}
public class LaserJammerConfig
{
public double MaxJammingCooldown { get; set; }
public double MaxJammingPower { get; set; }
public double InitialJammingPower { get; set; }
public double PowerIncreaseRate { get; set; }
public LaserJammerConfig()
{
MaxJammingCooldown = 5.0;
MaxJammingPower = 10000.0;
InitialJammingPower = 4000.0;
PowerIncreaseRate = 2000.0; // 每秒增加的功率
}
}

View File

@ -8,12 +8,13 @@ namespace ActiveProtect.SimulationEnvironment
public Vector3D Position { get; set; } = position;
public Orientation Orientation { get; set; } = orientation;
public ISimulationManager SimulationManager { get; set; } = simulationManager;
public bool IsActive { get; protected set; } = true;
public abstract void Update(double deltaTime);
public virtual string GetStatus()
{
return $"{GetType().Name} {Id} at {Position}, Orientation: {Orientation}";
return $"{GetType().Name} {Id} at {Position}, Orientation: {Orientation}, Active: {IsActive}";
}
protected void PublishEvent(SimulationEvent evt)
@ -22,5 +23,17 @@ namespace ActiveProtect.SimulationEnvironment
evt.Timestamp = SimulationManager.CurrentTime;
SimulationManager.PublishEvent(evt);
}
protected virtual void Activate()
{
IsActive = true;
PublishEvent(new EntityActivatedEvent { ActivatedEntityId = Id });
}
protected virtual void Deactivate()
{
IsActive = false;
PublishEvent(new EntityDeactivatedEvent { DeactivatedEntityId = Id });
}
}
}

View File

@ -31,4 +31,14 @@ namespace ActiveProtect.SimulationEnvironment
{
public string? TargetId { get; set; }
}
public class EntityActivatedEvent : SimulationEvent
{
public string? ActivatedEntityId { get; set; }
}
public class EntityDeactivatedEvent : SimulationEvent
{
public string? DeactivatedEntityId { get; set; }
}
}

View File

@ -9,12 +9,14 @@ namespace ActiveProtect.SimulationEnvironment
{
double CurrentTime { get; }
void AddElement(SimulationElement element);
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;
void UnsubscribeAllEvents(SimulationElement element);
}
public class SimulationManager : ISimulationManager
@ -24,6 +26,7 @@ namespace ActiveProtect.SimulationEnvironment
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)>>();
public SimulationManager(SimulationConfig config)
{
@ -36,17 +39,54 @@ namespace ActiveProtect.SimulationEnvironment
private void InitializeSimulation()
{
// 创建坦克(保持不变)
// 创建坦克
for (int i = 0; i < config.TankConfigs.Count; i++)
{
var tankConfig = config.TankConfigs[i];
Elements.Add(new Tank($"Tank_{i + 1}", tankConfig, this));
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 秒");
}
Missile missile = missileConfig.Type switch
{
MissileType.SemiActiveLaserGuidance => new LaserSemiActiveGuidedMissile(
@ -67,7 +107,7 @@ namespace ActiveProtect.SimulationEnvironment
for (int i = 0; i < config.LaserDesignatorConfigs.Count; i++)
{
var laserDesignatorConfig = config.LaserDesignatorConfigs[i];
var laserDesignator = new LaserDesignator($"LD_{i + 1}", laserDesignatorConfig, this);
var laserDesignator = new LaserDesignator($"LD_{i + 1}", "Tank_1", laserDesignatorConfig, this);
Elements.Add(laserDesignator);
laserDesignator.ActivateLaser(); // 激活激光目标指示器
}
@ -93,6 +133,17 @@ namespace ActiveProtect.SimulationEnvironment
eventHandlers[eventType] = new List<Delegate>();
}
eventHandlers[eventType].Add(handler);
// 记录订阅关系
var element = Elements.FirstOrDefault(e => e.GetType().GetMethods().Any(m => m.Name == handler.Method.Name));
if (element != null)
{
if (!elementSubscriptions.ContainsKey(element))
{
elementSubscriptions[element] = new List<(Type, Delegate)>();
}
elementSubscriptions[element].Add((eventType, handler));
}
}
public void UnsubscribeFromEvent<T>(Action<T> handler) where T : SimulationEvent
@ -102,6 +153,28 @@ namespace ActiveProtect.SimulationEnvironment
{
eventHandlers[eventType].Remove(handler);
}
// 移除订阅关系记录
var element = Elements.FirstOrDefault(e => e.GetType().GetMethods().Any(m => m.Name == handler.Method.Name));
if (element != null && elementSubscriptions.ContainsKey(element))
{
elementSubscriptions[element].RemoveAll(s => Delegate.Equals(s.Item2, handler));
}
}
public void UnsubscribeAllEvents(SimulationElement element)
{
if (elementSubscriptions.ContainsKey(element))
{
foreach (var subscription in elementSubscriptions[element])
{
if (eventHandlers.ContainsKey(subscription.Item1))
{
eventHandlers[subscription.Item1].Remove(subscription.Item2);
}
}
elementSubscriptions.Remove(element);
}
}
public void Update()
@ -112,14 +185,21 @@ namespace ActiveProtect.SimulationEnvironment
foreach (var element in Elements.ToList())
{
element.Update(config.SimulationTimeStep);
if (element.IsActive)
{
element.Update(config.SimulationTimeStep);
}
else
{
UnsubscribeAllEvents(element);
}
}
// 移除不活跃的元素
Elements.RemoveAll(e => (e is Tank tank && !tank.IsActive) || (e is Missile missile && !missile.IsActive));
Elements.RemoveAll(e => !e.IsActive);
// 检查是否所有导弹都结束飞行
if (!Elements.Any(e => e is Missile))
if (!Elements.Any(e => e is Missile && e.IsActive))
{
EndSimulation();
}
@ -158,19 +238,11 @@ namespace ActiveProtect.SimulationEnvironment
// 对坦克造成伤害
tank.TakeDamage(damage, true);
// 移除已爆炸的导弹
RemoveEntity(missileId);
// 记录击中事件
LogHitEvent(targetId, missileId, damage);
}
}
private void RemoveEntity(string missileId)
{
Elements.Remove(GetEntityById(missileId));
}
private double CalculateMissileDamage(Missile missile)
{
// 这里可以根据导弹类型、速度等因素计算伤害
@ -178,9 +250,14 @@ namespace ActiveProtect.SimulationEnvironment
return 100;
}
private void LogHitEvent(string targetId, string missileId, double damage)
private static void LogHitEvent(string targetId, string missileId, double damage)
{
Console.WriteLine($"目标 {targetId} 被导弹 {missileId} 击中,造成 {damage} 点伤害");
}
public void AddElement(SimulationElement element)
{
Elements.Add(element);
}
}
}