Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / activity / role / enemy / state / AiFollowUpState.cs
  1.  
  2. using System;
  3. using Godot;
  4.  
  5. namespace EnemyState;
  6.  
  7. /// <summary>
  8. /// 目标在视野内, 跟进目标, 如果距离在子弹有效射程内, 则开火
  9. /// </summary>
  10. public class AiFollowUpState : StateBase<Enemy, AIStateEnum>
  11. {
  12. //导航目标点刷新计时器
  13. private float _navigationUpdateTimer = 0;
  14. private float _navigationInterval = 0.3f;
  15.  
  16. public AiFollowUpState() : base(AIStateEnum.AiFollowUp)
  17. {
  18. }
  19.  
  20. public override void Enter(AIStateEnum prev, params object[] args)
  21. {
  22. if (Master.LookTarget == null)
  23. {
  24. throw new Exception("进入 AIAdvancedStateEnum.AiFollowUp 状态时角色没有攻击目标!");
  25. }
  26. _navigationUpdateTimer = 0;
  27. Master.TargetInView = true;
  28. }
  29.  
  30. public override void Process(float delta)
  31. {
  32. //先检查弹药是否打光
  33. if (Master.IsAllWeaponTotalAmmoEmpty())
  34. {
  35. //再寻找是否有可用的武器
  36. var targetWeapon = Master.FindTargetWeapon();
  37. if (targetWeapon != null)
  38. {
  39. ChangeState(AIStateEnum.AiFindAmmo, targetWeapon);
  40. return;
  41. }
  42. else
  43. {
  44. //切换到随机移动状态
  45. ChangeState(AIStateEnum.AiSurround);
  46. }
  47. }
  48.  
  49. var playerPos = Master.LookTarget.GetCenterPosition();
  50.  
  51. //更新玩家位置
  52. if (_navigationUpdateTimer <= 0)
  53. {
  54. //每隔一段时间秒更改目标位置
  55. _navigationUpdateTimer = _navigationInterval;
  56. Master.NavigationAgent2D.TargetPosition = playerPos;
  57. }
  58. else
  59. {
  60. _navigationUpdateTimer -= delta;
  61. }
  62.  
  63. //是否在攻击范围内
  64. var inAttackRange = false;
  65.  
  66. var weapon = Master.WeaponPack.ActiveItem;
  67. var distanceSquared = Master.Position.DistanceSquaredTo(playerPos);
  68. if (weapon != null)
  69. {
  70. inAttackRange = distanceSquared <= Mathf.Pow(Master.GetWeaponRange(0.7f), 2);
  71. }
  72. if (!Master.NavigationAgent2D.IsNavigationFinished())
  73. {
  74. //移动
  75. Master.DoMove();
  76. }
  77. else
  78. {
  79. //站立
  80. Master.DoIdle();
  81. }
  82.  
  83. //检测玩家是否在视野内
  84. if (Master.IsInTailAfterViewRange(playerPos))
  85. {
  86. Master.TargetInView = !Master.TestViewRayCast(playerPos);
  87. //关闭射线检测
  88. Master.TestViewRayCastOver();
  89. }
  90. else
  91. {
  92. Master.TargetInView = false;
  93. }
  94.  
  95. //在视野中
  96. if (Master.TargetInView)
  97. {
  98. //更新标记位置
  99. Master.UpdateMarkTargetPosition();
  100. if (inAttackRange) //在攻击范围内
  101. {
  102. //距离够近, 可以切换到环绕模式
  103. if (distanceSquared <= Mathf.Pow(Utils.GetConfigRangeStart(weapon.Attribute.Bullet.DistanceRange), 2) * 0.7f)
  104. {
  105. ChangeState(AIStateEnum.AiSurround);
  106. }
  107. else if (weapon.TriggerIsReady()) //可以攻击
  108. {
  109. //攻击状态
  110. ChangeState(AIStateEnum.AiAttack);
  111. }
  112. }
  113. }
  114. else //不在视野中
  115. {
  116. ChangeState(AIStateEnum.AiTailAfter);
  117. }
  118. }
  119.  
  120. public override void DebugDraw()
  121. {
  122. var playerPos = Master.LookTarget.GetCenterPosition();
  123. Master.DrawLine(new Vector2(0, -8), Master.ToLocal(playerPos), Colors.Red);
  124. }
  125. }