Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / activity / role / ai / state / AiSurroundState.cs
@小李xl 小李xl on 24 Mar 2024 5 KB 抽出AiRole类
  1.  
  2. using System;
  3. using Godot;
  4.  
  5. namespace AiState;
  6.  
  7. /// <summary>
  8. /// 距离目标足够近, 在目标附近随机移动, 并开火
  9. /// </summary>
  10. public class AiSurroundState : StateBase<AiRole, AIStateEnum>
  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(AIStateEnum.AiSurround)
  26. {
  27. }
  28.  
  29. public override void Enter(AIStateEnum 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(AIStateEnum.AiFindAmmo, targetWeapon);
  51. return;
  52. }
  53. }
  54.  
  55. var playerPos = Master.LookTarget.GetCenterPosition();
  56.  
  57. //检测玩家是否在视野内
  58. if (Master.IsInTailAfterViewRange(playerPos))
  59. {
  60. Master.TargetInView = !Master.TestViewRayCast(playerPos);
  61. //关闭射线检测
  62. Master.TestViewRayCastOver();
  63. }
  64. else
  65. {
  66. Master.TargetInView = false;
  67. }
  68.  
  69. //在视野中
  70. if (Master.TargetInView)
  71. {
  72. //更新标记位置
  73. Master.UpdateMarkTargetPosition();
  74. if (_pauseTimer >= 0)
  75. {
  76. Master.AnimatedSprite.Play(AnimatorNames.Idle);
  77. _pauseTimer -= delta;
  78. }
  79. else if (_isMoveOver) //移动已经完成
  80. {
  81. RunOver(playerPos);
  82. _isMoveOver = false;
  83. }
  84. else
  85. {
  86. var masterPosition = Master.Position;
  87. if (_lockTimer >= 1) //卡在一个点超过一秒
  88. {
  89. RunOver(playerPos);
  90. _isMoveOver = false;
  91. _lockTimer = 0;
  92. }
  93. else if (Master.NavigationAgent2D.IsNavigationFinished()) //到达终点
  94. {
  95. _pauseTimer = Utils.Random.RandomRangeFloat(0f, 0.5f);
  96. _isMoveOver = true;
  97. _moveFlag = false;
  98. //站立
  99. Master.DoIdle();
  100. }
  101. else if (!_moveFlag)
  102. {
  103. _moveFlag = true;
  104. //移动
  105. Master.DoMove();
  106. }
  107. else
  108. {
  109. var lastSlideCollision = Master.GetLastSlideCollision();
  110. if (lastSlideCollision != null && lastSlideCollision.GetCollider() is Role) //碰到其他角色
  111. {
  112. _pauseTimer = Utils.Random.RandomRangeFloat(0f, 0.3f);
  113. _isMoveOver = true;
  114. _moveFlag = false;
  115. //站立
  116. Master.DoIdle();
  117. }
  118. else
  119. {
  120. //移动
  121. Master.DoMove();
  122. }
  123.  
  124. if (_prevPos.DistanceSquaredTo(masterPosition) <= 1 * delta)
  125. {
  126. _lockTimer += delta;
  127. }
  128. else
  129. {
  130. _lockTimer = 0;
  131. _prevPos = masterPosition;
  132. }
  133. }
  134.  
  135. var weapon = Master.WeaponPack.ActiveItem;
  136. if (weapon != null)
  137. {
  138. if (masterPosition.DistanceSquaredTo(playerPos) > Mathf.Pow(Master.GetWeaponRange(0.7f), 2)) //玩家离开正常射击范围
  139. {
  140. ChangeState(AIStateEnum.AiFollowUp);
  141. }
  142. else if (!Master.IsAttack && weapon.TriggerIsReady()) //可以攻击
  143. {
  144. //发起攻击
  145. ChangeState(AIStateEnum.AiAttack);
  146. }
  147. }
  148. else
  149. {
  150. if (masterPosition.DistanceSquaredTo(playerPos) > Mathf.Pow(Master.ViewRange * 0.7f, 2)) //玩家离开正常射击范围
  151. {
  152. ChangeState(AIStateEnum.AiFollowUp);
  153. }
  154. else if (!Master.IsAttack && Master.NoWeaponAttack) //可以在没有武器时发起攻击
  155. {
  156. //攻击状态
  157. ChangeState(AIStateEnum.AiAttack);
  158. }
  159. }
  160. }
  161. }
  162. else //目标离开视野
  163. {
  164. ChangeState(AIStateEnum.AiTailAfter);
  165. }
  166. }
  167.  
  168. private void RunOver(Vector2 targetPos)
  169. {
  170. var weapon = Master.WeaponPack.ActiveItem;
  171. var distance = (int)(weapon == null ? 150 : (Utils.GetConfigRangeStart(weapon.Attribute.Bullet.DistanceRange) * 0.7f));
  172. _nextPosition = new Vector2(
  173. targetPos.X + Utils.Random.RandomRangeInt(-distance, distance),
  174. targetPos.Y + Utils.Random.RandomRangeInt(-distance, distance)
  175. );
  176. Master.NavigationAgent2D.TargetPosition = _nextPosition;
  177. }
  178.  
  179. public override void DebugDraw()
  180. {
  181. Master.DrawLine(new Vector2(0, -8), Master.ToLocal(_nextPosition), Colors.White);
  182. }
  183. }