Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / activity / role / enemy / advancedState / AiSurroundState.cs
@小李xl 小李xl on 11 Nov 2023 6 KB 第二种敌人攻击状态
  1.  
  2. using Godot;
  3.  
  4. namespace AdvancedState;
  5.  
  6. /// <summary>
  7. /// 距离目标足够近, 在目标附近随机移动, 并开火
  8. /// </summary>
  9. public class AiSurroundState : StateBase<AdvancedEnemy, AiStateEnum>
  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(AiStateEnum.AiSurround)
  25. {
  26. }
  27.  
  28. public override void Enter(AiStateEnum 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. //先检查弹药是否打光
  39. if (Master.IsAllWeaponTotalAmmoEmpty())
  40. {
  41. //再寻找是否有可用的武器
  42. var targetWeapon = Master.FindTargetWeapon();
  43. if (targetWeapon != null)
  44. {
  45. ChangeState(AiStateEnum.AiFindAmmo, targetWeapon);
  46. return;
  47. }
  48. }
  49.  
  50. var playerPos = Player.Current.GetCenterPosition();
  51. var weapon = Master.WeaponPack.ActiveItem;
  52.  
  53. //枪口指向玩家
  54. Master.LookTargetPosition(playerPos);
  55.  
  56. //检测玩家是否在视野内
  57. if (Master.IsInTailAfterViewRange(playerPos))
  58. {
  59. Master.TargetInView = !Master.TestViewRayCast(playerPos);
  60. //关闭射线检测
  61. Master.TestViewRayCastOver();
  62. }
  63. else
  64. {
  65. Master.TargetInView = false;
  66. }
  67.  
  68. //在视野中, 或者锁敌状态下, 或者攻击状态下, 继续保持原本逻辑
  69. if (Master.TargetInView ||
  70. (weapon != null && weapon.Attribute.AiAttackAttr.FiringStand &&
  71. (Master.AttackState == AiAttackState.LockingTime || Master.AttackState == AiAttackState.Attack)
  72. ))
  73. {
  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. if (_lockTimer >= 1) //卡在一个点超过一秒
  87. {
  88. RunOver(playerPos);
  89. _isMoveOver = false;
  90. _lockTimer = 0;
  91. }
  92. else if (Master.NavigationAgent2D.IsNavigationFinished()) //到达终点
  93. {
  94. _pauseTimer = Utils.Random.RandomRangeFloat(0f, 0.5f);
  95. _isMoveOver = true;
  96. _moveFlag = false;
  97. Master.BasisVelocity = Vector2.Zero;
  98. }
  99. else if (!_moveFlag)
  100. {
  101. _moveFlag = true;
  102. //计算移动
  103. var nextPos = Master.NavigationAgent2D.GetNextPathPosition();
  104. Master.AnimatedSprite.Play(AnimatorNames.Run);
  105. Master.BasisVelocity =
  106. (nextPos - Master.GlobalPosition - Master.NavigationPoint.Position).Normalized() *
  107. Master.RoleState.MoveSpeed;
  108. }
  109. else
  110. {
  111. var pos = Master.GlobalPosition;
  112. var lastSlideCollision = Master.GetLastSlideCollision();
  113. if (lastSlideCollision != null && lastSlideCollision.GetCollider() is AdvancedRole) //碰到其他角色
  114. {
  115. _pauseTimer = Utils.Random.RandomRangeFloat(0f, 0.3f);
  116. _isMoveOver = true;
  117. _moveFlag = false;
  118. Master.BasisVelocity = Vector2.Zero;
  119. }
  120. else
  121. {
  122. //判断开火状态, 进行移动
  123. if (weapon == null || !weapon.Attribute.AiAttackAttr.FiringStand ||
  124. (Master.AttackState != AiAttackState.LockingTime && Master.AttackState != AiAttackState.Attack))
  125. { //正常移动
  126. //计算移动
  127. var nextPos = Master.NavigationAgent2D.GetNextPathPosition();
  128. Master.AnimatedSprite.Play(AnimatorNames.Run);
  129. Master.BasisVelocity = (nextPos - pos - Master.NavigationPoint.Position).Normalized() *
  130. Master.RoleState.MoveSpeed;
  131. }
  132. else //站立不动
  133. {
  134. Master.AnimatedSprite.Play(AnimatorNames.Idle);
  135. Master.BasisVelocity = Vector2.Zero;
  136. }
  137. }
  138.  
  139. if (_prevPos.DistanceSquaredTo(pos) <= 0.01f)
  140. {
  141. _lockTimer += delta;
  142. }
  143. else
  144. {
  145. _prevPos = pos;
  146. }
  147. }
  148.  
  149. if (weapon != null)
  150. {
  151. var position = Master.GlobalPosition;
  152. if (position.DistanceSquaredTo(playerPos) > Mathf.Pow(Master.GetWeaponRange(0.7f), 2)) //玩家离开正常射击范围
  153. {
  154. ChangeState(AiStateEnum.AiFollowUp);
  155. }
  156. else
  157. {
  158. //发起攻击
  159. Master.EnemyAttack();
  160. }
  161. }
  162. }
  163. }
  164. else //目标离开视野
  165. {
  166. ChangeState(AiStateEnum.AiTailAfter);
  167. }
  168. }
  169.  
  170. private void RunOver(Vector2 targetPos)
  171. {
  172. var weapon = Master.WeaponPack.ActiveItem;
  173. var distance = (int)(weapon == null ? 150 : (Utils.GetConfigRangeStart(weapon.Attribute.Bullet.DistanceRange) * 0.7f));
  174. _nextPosition = new Vector2(
  175. targetPos.X + Utils.Random.RandomRangeInt(-distance, distance),
  176. targetPos.Y + Utils.Random.RandomRangeInt(-distance, distance)
  177. );
  178. Master.NavigationAgent2D.TargetPosition = _nextPosition;
  179. }
  180.  
  181. public override void DebugDraw()
  182. {
  183. Master.DrawLine(new Vector2(0, -8), Master.ToLocal(_nextPosition), Colors.White);
  184. }
  185. }