Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / activity / role / enemy / state / AiSurroundState.cs
  1.  
  2. using System;
  3. using Godot;
  4.  
  5. namespace EnemyState;
  6.  
  7. /// <summary>
  8. /// 距离目标足够近, 在目标附近随机移动, 并开火
  9. /// </summary>
  10. public class AiSurroundState : StateBase<Enemy, 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. 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. //更新标记位置
  74. Master.UpdateMarkTargetPosition();
  75. if (_pauseTimer >= 0)
  76. {
  77. Master.AnimatedSprite.Play(AnimatorNames.Idle);
  78. _pauseTimer -= delta;
  79. }
  80. else if (_isMoveOver) //移动已经完成
  81. {
  82. RunOver(playerPos);
  83. _isMoveOver = false;
  84. }
  85. else
  86. {
  87. var masterPosition = Master.Position;
  88. if (_lockTimer >= 1) //卡在一个点超过一秒
  89. {
  90. RunOver(playerPos);
  91. _isMoveOver = false;
  92. _lockTimer = 0;
  93. }
  94. else if (Master.NavigationAgent2D.IsNavigationFinished()) //到达终点
  95. {
  96. _pauseTimer = Utils.Random.RandomRangeFloat(0f, 0.5f);
  97. _isMoveOver = true;
  98. _moveFlag = false;
  99. //站立
  100. Master.DoIdle();
  101. }
  102. else if (!_moveFlag)
  103. {
  104. _moveFlag = true;
  105. //移动
  106. Master.DoMove();
  107. }
  108. else
  109. {
  110. var lastSlideCollision = Master.GetLastSlideCollision();
  111. if (lastSlideCollision != null && lastSlideCollision.GetCollider() is Role) //碰到其他角色
  112. {
  113. _pauseTimer = Utils.Random.RandomRangeFloat(0f, 0.3f);
  114. _isMoveOver = true;
  115. _moveFlag = false;
  116. //站立
  117. Master.DoIdle();
  118. }
  119. else
  120. {
  121. //移动
  122. Master.DoMove();
  123. }
  124.  
  125. if (_prevPos.DistanceSquaredTo(masterPosition) <= 1 * delta)
  126. {
  127. _lockTimer += delta;
  128. }
  129. else
  130. {
  131. _lockTimer = 0;
  132. _prevPos = masterPosition;
  133. }
  134. }
  135.  
  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 (weapon.TriggerIsReady()) //可以攻击
  143. {
  144. //发起攻击
  145. ChangeState(AIStateEnum.AiAttack);
  146. }
  147. }
  148. }
  149. }
  150. else //目标离开视野
  151. {
  152. ChangeState(AIStateEnum.AiTailAfter);
  153. }
  154. }
  155.  
  156. private void RunOver(Vector2 targetPos)
  157. {
  158. var weapon = Master.WeaponPack.ActiveItem;
  159. var distance = (int)(weapon == null ? 150 : (Utils.GetConfigRangeStart(weapon.Attribute.Bullet.DistanceRange) * 0.7f));
  160. _nextPosition = new Vector2(
  161. targetPos.X + Utils.Random.RandomRangeInt(-distance, distance),
  162. targetPos.Y + Utils.Random.RandomRangeInt(-distance, distance)
  163. );
  164. Master.NavigationAgent2D.TargetPosition = _nextPosition;
  165. }
  166.  
  167. public override void DebugDraw()
  168. {
  169. Master.DrawLine(new Vector2(0, -8), Master.ToLocal(_nextPosition), Colors.White);
  170. }
  171. }