Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / activity / role / enemy / normalState / AiSurroundState.cs
@小李xl 小李xl on 14 Nov 2023 5 KB 普通敌人环绕玩家状态
  1.  
  2. using Godot;
  3.  
  4. namespace NnormalState;
  5.  
  6. /// <summary>
  7. /// 距离目标足够近, 在目标附近随机移动, 并开火
  8. /// </summary>
  9. public class AiSurroundState : StateBase<Enemy, AINormalStateEnum>
  10. {
  11. //是否移动结束
  12. private bool _isMoveOver;
  13.  
  14. //移动停顿计时器
  15. private float _pauseTimer;
  16. private bool _moveFlag;
  17. //下一个移动点
  18. private Vector2 _nextPosition;
  19. //上一帧位置
  20. private Vector2 _prevPos;
  21. //卡在一个位置的时间
  22. private float _lockTimer;
  23.  
  24. public AiSurroundState() : base(AINormalStateEnum.AiSurround)
  25. {
  26. }
  27.  
  28. public override void Enter(AINormalStateEnum prev, params object[] args)
  29. {
  30. Master.TargetInView = true;
  31. _isMoveOver = true;
  32. _pauseTimer = 0;
  33. _moveFlag = false;
  34. }
  35.  
  36. public override void Process(float delta)
  37. {
  38. var playerPos = Player.Current.GetCenterPosition();
  39.  
  40. //枪口指向玩家
  41. Master.LookTargetPosition(playerPos);
  42.  
  43. //检测玩家是否在视野内
  44. if (Master.IsInTailAfterViewRange(playerPos))
  45. {
  46. Master.TargetInView = !Master.TestViewRayCast(playerPos);
  47. //关闭射线检测
  48. Master.TestViewRayCastOver();
  49. }
  50. else
  51. {
  52. Master.TargetInView = false;
  53. }
  54.  
  55. //在视野中, 或者锁敌状态下, 或者攻击状态下, 继续保持原本逻辑
  56. if (Master.TargetInView ||
  57. (Master.FiringStand &&
  58. (Master.AttackState == AiAttackState.LockingTime || Master.AttackState == AiAttackState.Attack)
  59. ))
  60. {
  61. if (_pauseTimer >= 0)
  62. {
  63. Master.AnimatedSprite.Play(AnimatorNames.Idle);
  64. _pauseTimer -= delta;
  65. }
  66. else if (_isMoveOver) //移动已经完成
  67. {
  68. RunOver(playerPos);
  69. _isMoveOver = false;
  70. }
  71. else
  72. {
  73. var masterPosition = Master.GlobalPosition;
  74. if (_lockTimer >= 1) //卡在一个点超过一秒
  75. {
  76. RunOver(playerPos);
  77. _isMoveOver = false;
  78. _lockTimer = 0;
  79. }
  80. else if (Master.NavigationAgent2D.IsNavigationFinished()) //到达终点
  81. {
  82. _pauseTimer = Utils.Random.RandomRangeFloat(0f, 0.5f);
  83. _isMoveOver = true;
  84. _moveFlag = false;
  85. Master.BasisVelocity = Vector2.Zero;
  86. }
  87. else if (!_moveFlag)
  88. {
  89. _moveFlag = true;
  90. //计算移动
  91. var nextPos = Master.NavigationAgent2D.GetNextPathPosition();
  92. Master.AnimatedSprite.Play(AnimatorNames.Run);
  93. Master.BasisVelocity =
  94. (nextPos - masterPosition - Master.NavigationPoint.Position).Normalized() *
  95. Master.RoleState.MoveSpeed;
  96. }
  97. else
  98. {
  99. var pos = masterPosition;
  100. var lastSlideCollision = Master.GetLastSlideCollision();
  101. if (lastSlideCollision != null && lastSlideCollision.GetCollider() is AdvancedRole) //碰到其他角色
  102. {
  103. _pauseTimer = Utils.Random.RandomRangeFloat(0f, 0.3f);
  104. _isMoveOver = true;
  105. _moveFlag = false;
  106. Master.BasisVelocity = Vector2.Zero;
  107. }
  108. else
  109. {
  110. //判断开火状态, 进行移动
  111. if (!Master.FiringStand ||
  112. (Master.AttackState != AiAttackState.LockingTime && Master.AttackState != AiAttackState.Attack))
  113. { //正常移动
  114. //计算移动
  115. var nextPos = Master.NavigationAgent2D.GetNextPathPosition();
  116. Master.AnimatedSprite.Play(AnimatorNames.Run);
  117. Master.BasisVelocity = (nextPos - pos - Master.NavigationPoint.Position).Normalized() *
  118. Master.RoleState.MoveSpeed;
  119. }
  120. else //站立不动
  121. {
  122. Master.AnimatedSprite.Play(AnimatorNames.Idle);
  123. Master.BasisVelocity = Vector2.Zero;
  124. }
  125. }
  126.  
  127. if (_prevPos.DistanceSquaredTo(pos) <= 1 * delta)
  128. {
  129. _lockTimer += delta;
  130. }
  131. else
  132. {
  133. _prevPos = pos;
  134. }
  135. }
  136. if (masterPosition.DistanceSquaredTo(playerPos) > Mathf.Pow(Master.GetAttackRange() * 0.7f, 2)) //玩家离开正常射击范围
  137. {
  138. ChangeState(AINormalStateEnum.AiFollowUp);
  139. }
  140. else
  141. {
  142. //发起攻击
  143. Master.Attack();
  144. }
  145. }
  146. }
  147. else //目标离开视野
  148. {
  149. ChangeState(AINormalStateEnum.AiTailAfter);
  150. }
  151. }
  152.  
  153. private void RunOver(Vector2 targetPos)
  154. {
  155. var distance = (int)(Master.GetAttackRange() * 0.7f);
  156. _nextPosition = new Vector2(
  157. targetPos.X + Utils.Random.RandomRangeInt(-distance, distance),
  158. targetPos.Y + Utils.Random.RandomRangeInt(-distance, distance)
  159. );
  160. Master.NavigationAgent2D.TargetPosition = _nextPosition;
  161. }
  162.  
  163. public override void DebugDraw()
  164. {
  165. Master.DrawLine(new Vector2(0, -8), Master.ToLocal(_nextPosition), Colors.White);
  166. }
  167. }