Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / role / enemy / state / AiSurroundState.cs
  1.  
  2. using Godot;
  3.  
  4. /// <summary>
  5. /// 距离目标足够近, 在目标附近随机移动, 并开火
  6. /// </summary>
  7. public class AiSurroundState : StateBase<Enemy, AiStateEnum>
  8. {
  9. /// <summary>
  10. /// 目标是否在视野内
  11. /// </summary>
  12. public bool IsInView = true;
  13.  
  14. //是否移动结束
  15. private bool _isMoveOver;
  16.  
  17. //移动停顿计时器
  18. private float _pauseTimer;
  19. private bool _moveFlag;
  20. //下一个移动点
  21. private Vector2 _nextPosition;
  22. //上一帧位置
  23. private Vector2 _prevPos;
  24. //卡在一个位置的时间
  25. private float _lockTimer;
  26.  
  27. public AiSurroundState() : base(AiStateEnum.AiSurround)
  28. {
  29. }
  30.  
  31. public override void Enter(AiStateEnum prev, params object[] args)
  32. {
  33. IsInView = true;
  34. _isMoveOver = true;
  35. _pauseTimer = 0;
  36. _moveFlag = false;
  37. }
  38.  
  39. public override void Process(float delta)
  40. {
  41. //先检查弹药是否打光
  42. if (Master.IsAllWeaponTotalAmmoEmpty())
  43. {
  44. //再寻找是否有可用的武器
  45. var targetWeapon = Master.FindTargetWeapon();
  46. if (targetWeapon != null)
  47. {
  48. ChangeStateLate(AiStateEnum.AiFindAmmo, targetWeapon);
  49. return;
  50. }
  51. }
  52.  
  53. var playerPos = Player.Current.GetCenterPosition();
  54. var weapon = Master.Holster.ActiveWeapon;
  55.  
  56. //枪口指向玩家
  57. Master.LookTargetPosition(playerPos);
  58.  
  59. //检测玩家是否在视野内
  60. if (Master.IsInTailAfterViewRange(playerPos))
  61. {
  62. IsInView = !Master.TestViewRayCast(playerPos);
  63. //关闭射线检测
  64. Master.TestViewRayCastOver();
  65. }
  66. else
  67. {
  68. IsInView = false;
  69. }
  70.  
  71. if (IsInView)
  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. if (_lockTimer >= 1) //卡在一个点超过一秒
  86. {
  87. RunOver(playerPos);
  88. _isMoveOver = false;
  89. _lockTimer = 0;
  90. }
  91. else if (Master.NavigationAgent2D.IsNavigationFinished()) //到达终点
  92. {
  93. _pauseTimer = Utils.RandomRangeFloat(0f, 0.5f);
  94. _isMoveOver = true;
  95. _moveFlag = false;
  96. Master.BasisVelocity = Vector2.Zero;
  97. }
  98. else if (!_moveFlag)
  99. {
  100. _moveFlag = true;
  101. //计算移动
  102. var pos = Master.GlobalPosition;
  103. var nextPos = Master.NavigationAgent2D.GetNextPathPosition();
  104. Master.AnimatedSprite.Play(AnimatorNames.Run);
  105. Master.BasisVelocity = (nextPos - Master.GlobalPosition - Master.NavigationPoint.Position).Normalized() *
  106. Master.MoveSpeed;
  107. }
  108. else
  109. {
  110. var pos = Master.GlobalPosition;
  111. var lastSlideCollision = Master.GetLastSlideCollision();
  112. if (lastSlideCollision != null && lastSlideCollision.GetCollider() is Role) //碰到其他角色
  113. {
  114. _pauseTimer = Utils.RandomRangeFloat(0f, 0.3f);
  115. _isMoveOver = true;
  116. _moveFlag = false;
  117. Master.BasisVelocity = Vector2.Zero;
  118. }
  119. else
  120. {
  121. //计算移动
  122. var nextPos = Master.NavigationAgent2D.GetNextPathPosition();
  123. Master.AnimatedSprite.Play(AnimatorNames.Run);
  124. Master.BasisVelocity = (nextPos - pos - Master.NavigationPoint.Position).Normalized() *
  125. Master.MoveSpeed;
  126. }
  127. if (_prevPos.DistanceSquaredTo(pos) <= 0.01f)
  128. {
  129. _lockTimer += delta;
  130. }
  131. else
  132. {
  133. _prevPos = pos;
  134. }
  135. }
  136.  
  137. if (weapon != null)
  138. {
  139. var position = Master.GlobalPosition;
  140. if (position.DistanceSquaredTo(playerPos) > Mathf.Pow(Master.GetWeaponRange(0.7f), 2)) //玩家离开正常射击范围
  141. {
  142. ChangeStateLate(AiStateEnum.AiFollowUp);
  143. }
  144. else
  145. {
  146. //发起攻击
  147. Master.EnemyAttack(delta);
  148. }
  149. }
  150. }
  151. }
  152. else //目标离开视野
  153. {
  154. ChangeStateLate(AiStateEnum.AiTailAfter);
  155. }
  156. }
  157.  
  158. private void RunOver(Vector2 targetPos)
  159. {
  160. var weapon = Master.Holster.ActiveWeapon;
  161. var distance = (int)(weapon == null ? 150 : (weapon.Attribute.MinDistance * 0.7f));
  162. _nextPosition = new Vector2(
  163. targetPos.X + Utils.RandomRangeInt(-distance, distance),
  164. targetPos.Y + Utils.RandomRangeInt(-distance, distance)
  165. );
  166. Master.NavigationAgent2D.TargetPosition = _nextPosition;
  167. }
  168.  
  169. public override void DebugDraw()
  170. {
  171. Master.DrawLine(new Vector2(0, -8), Master.ToLocal(_nextPosition), Colors.White);
  172. }
  173. }