Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / activity / role / enemy / advancedState / AiSurroundState.cs
  1.  
  2. using System;
  3. using Godot;
  4.  
  5. namespace AdvancedState;
  6.  
  7. /// <summary>
  8. /// 距离目标足够近, 在目标附近随机移动, 并开火
  9. /// </summary>
  10. public class AiSurroundState : StateBase<AdvancedEnemy, AIAdvancedStateEnum>
  11. {
  12. //是否移动结束
  13. private bool _isMoveOver;
  14.  
  15. //移动停顿计时器
  16. private float _pauseTimer;
  17. private bool _moveFlag;
  18. //下一个移动点
  19. private Vector2 _nextPosition;
  20. //上一帧位置
  21. private Vector2 _prevPos;
  22. //卡在一个位置的时间
  23. private float _lockTimer;
  24.  
  25. public AiSurroundState() : base(AIAdvancedStateEnum.AiSurround)
  26. {
  27. }
  28.  
  29. public override void Enter(AIAdvancedStateEnum prev, params object[] args)
  30. {
  31. if (Master.LookTarget == null)
  32. {
  33. throw new Exception("进入 AIAdvancedStateEnum.AiSurround 状态时角色没有攻击目标!");
  34. }
  35. Master.TargetInView = true;
  36. _isMoveOver = true;
  37. _pauseTimer = 0;
  38. _moveFlag = false;
  39. }
  40.  
  41. public override void Process(float delta)
  42. {
  43. //先检查弹药是否打光
  44. if (Master.IsAllWeaponTotalAmmoEmpty())
  45. {
  46. //再寻找是否有可用的武器
  47. var targetWeapon = Master.FindTargetWeapon();
  48. if (targetWeapon != null)
  49. {
  50. ChangeState(AIAdvancedStateEnum.AiFindAmmo, targetWeapon);
  51. return;
  52. }
  53. }
  54.  
  55. var playerPos = Master.LookTarget.GetCenterPosition();
  56. var weapon = Master.WeaponPack.ActiveItem;
  57.  
  58. //检测玩家是否在视野内
  59. if (Master.IsInTailAfterViewRange(playerPos))
  60. {
  61. Master.TargetInView = !Master.TestViewRayCast(playerPos);
  62. //关闭射线检测
  63. Master.TestViewRayCastOver();
  64. }
  65. else
  66. {
  67. Master.TargetInView = false;
  68. }
  69.  
  70. //在视野中
  71. if (Master.TargetInView)
  72. {
  73. if (_pauseTimer >= 0)
  74. {
  75. Master.AnimatedSprite.Play(AnimatorNames.Idle);
  76. _pauseTimer -= delta;
  77. }
  78. else if (_isMoveOver) //移动已经完成
  79. {
  80. RunOver(playerPos);
  81. _isMoveOver = false;
  82. }
  83. else
  84. {
  85. var masterPosition = Master.Position;
  86. if (_lockTimer >= 1) //卡在一个点超过一秒
  87. {
  88. RunOver(playerPos);
  89. _isMoveOver = false;
  90. _lockTimer = 0;
  91. }
  92. else if (Master.NavigationAgent2D.IsNavigationFinished()) //到达终点
  93. {
  94. _pauseTimer = Utils.Random.RandomRangeFloat(0f, 0.5f);
  95. _isMoveOver = true;
  96. _moveFlag = false;
  97. //站立
  98. Master.DoIdle();
  99. }
  100. else if (!_moveFlag)
  101. {
  102. _moveFlag = true;
  103. //移动
  104. Master.DoMove();
  105. }
  106. else
  107. {
  108. var lastSlideCollision = Master.GetLastSlideCollision();
  109. if (lastSlideCollision != null && lastSlideCollision.GetCollider() is AdvancedRole) //碰到其他角色
  110. {
  111. _pauseTimer = Utils.Random.RandomRangeFloat(0f, 0.3f);
  112. _isMoveOver = true;
  113. _moveFlag = false;
  114. //站立
  115. Master.DoIdle();
  116. }
  117. else
  118. {
  119. //移动
  120. Master.DoMove();
  121. }
  122.  
  123. if (_prevPos.DistanceSquaredTo(masterPosition) <= 1 * delta)
  124. {
  125. _lockTimer += delta;
  126. }
  127. else
  128. {
  129. _lockTimer = 0;
  130. _prevPos = masterPosition;
  131. }
  132. }
  133.  
  134. if (weapon != null)
  135. {
  136. if (masterPosition.DistanceSquaredTo(playerPos) > Mathf.Pow(Master.GetWeaponRange(0.7f), 2)) //玩家离开正常射击范围
  137. {
  138. ChangeState(AIAdvancedStateEnum.AiFollowUp);
  139. }
  140. else if (weapon.TriggerIsReady()) //可以攻击
  141. {
  142. //发起攻击
  143. ChangeState(AIAdvancedStateEnum.AiAttack);
  144. }
  145. }
  146. }
  147. }
  148. else //目标离开视野
  149. {
  150. ChangeState(AIAdvancedStateEnum.AiTailAfter);
  151. }
  152. }
  153.  
  154. private void RunOver(Vector2 targetPos)
  155. {
  156. var weapon = Master.WeaponPack.ActiveItem;
  157. var distance = (int)(weapon == null ? 150 : (Utils.GetConfigRangeStart(weapon.Attribute.Bullet.DistanceRange) * 0.7f));
  158. _nextPosition = new Vector2(
  159. targetPos.X + Utils.Random.RandomRangeInt(-distance, distance),
  160. targetPos.Y + Utils.Random.RandomRangeInt(-distance, distance)
  161. );
  162. Master.NavigationAgent2D.TargetPosition = _nextPosition;
  163. }
  164.  
  165. public override void DebugDraw()
  166. {
  167. Master.DrawLine(new Vector2(0, -8), Master.ToLocal(_nextPosition), Colors.White);
  168. }
  169. }