Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / activity / role / enemy / normalState / AiSurroundState.cs
@小李xl 小李xl on 15 Nov 2023 4 KB 普通ai攻击状态
  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. {
  58. if (_pauseTimer >= 0)
  59. {
  60. Master.AnimatedSprite.Play(AnimatorNames.Idle);
  61. _pauseTimer -= delta;
  62. }
  63. else if (_isMoveOver) //移动已经完成
  64. {
  65. RunOver(playerPos);
  66. _isMoveOver = false;
  67. }
  68. else
  69. {
  70. var masterPosition = Master.Position;
  71. if (_lockTimer >= 1) //卡在一个点超过一秒
  72. {
  73. RunOver(playerPos);
  74. _isMoveOver = false;
  75. _lockTimer = 0;
  76. }
  77. else if (Master.NavigationAgent2D.IsNavigationFinished()) //到达终点
  78. {
  79. _pauseTimer = Utils.Random.RandomRangeFloat(0f, 0.5f);
  80. _isMoveOver = true;
  81. _moveFlag = false;
  82. Master.DoIdle();
  83. }
  84. else if (!_moveFlag)
  85. {
  86. _moveFlag = true;
  87. //计算移动
  88. Master.DoMove();
  89. }
  90. else
  91. {
  92. var lastSlideCollision = Master.GetLastSlideCollision();
  93. if (lastSlideCollision != null && lastSlideCollision.GetCollider() is AdvancedRole) //碰到其他角色
  94. {
  95. _pauseTimer = Utils.Random.RandomRangeFloat(0f, 0.3f);
  96. _isMoveOver = true;
  97. _moveFlag = false;
  98. Master.DoIdle();
  99. }
  100. else
  101. {
  102. //计算移动
  103. Master.DoMove();
  104. }
  105. if (_prevPos.DistanceSquaredTo(masterPosition) <= 1 * delta)
  106. {
  107. _lockTimer += delta;
  108. }
  109. else
  110. {
  111. _lockTimer = 0;
  112. _prevPos = masterPosition;
  113. }
  114. }
  115. if (masterPosition.DistanceSquaredTo(playerPos) > Mathf.Pow(Master.GetAttackRange() * 0.7f, 2)) //玩家离开正常射击范围
  116. {
  117. ChangeState(AINormalStateEnum.AiFollowUp);
  118. }
  119. else if (Master.GetAttackTimer() <= 0) //发起攻击
  120. {
  121. ChangeState(AINormalStateEnum.AiAttack);
  122. }
  123. }
  124. }
  125. else //目标离开视野
  126. {
  127. ChangeState(AINormalStateEnum.AiTailAfter);
  128. }
  129. }
  130.  
  131. private void RunOver(Vector2 targetPos)
  132. {
  133. var distance = (int)(Master.GetAttackRange() * 0.7f);
  134. _nextPosition = new Vector2(
  135. targetPos.X + Utils.Random.RandomRangeInt(-distance, distance),
  136. targetPos.Y + Utils.Random.RandomRangeInt(-distance, distance)
  137. );
  138. Master.NavigationAgent2D.TargetPosition = _nextPosition;
  139. }
  140.  
  141. public override void DebugDraw()
  142. {
  143. Master.DrawLine(new Vector2(0, -8), Master.ToLocal(_nextPosition), Colors.White);
  144. }
  145. }