Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / role / enemy / state / AiSurroundState.cs
@小李xl 小李xl on 11 Dec 2022 4 KB 敌人寻找可用武器逻辑
  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.  
  20. //下一个移动点
  21. private Vector2 _nextPosition;
  22.  
  23. public AiSurroundState() : base(AiStateEnum.AiSurround)
  24. {
  25. }
  26.  
  27. public override void Enter(AiStateEnum prev, params object[] args)
  28. {
  29. IsInView = true;
  30. _isMoveOver = true;
  31. _pauseTimer = 0;
  32. }
  33.  
  34. public override void PhysicsProcess(float delta)
  35. {
  36. //先检查弹药是否打光
  37. if (Master.IsAllWeaponTotalAmmoEmpty())
  38. {
  39. //再寻找是否有可用的武器
  40. if (Master.CheckUsableWeaponInUnclaimed())
  41. {
  42. //切换到寻找武器状态
  43. ChangeStateLate(AiStateEnum.AiFindAmmo);
  44. return;
  45. }
  46. }
  47. var playerPos = Player.Current.GetCenterPosition();
  48. var weapon = Master.Holster.ActiveWeapon;
  49.  
  50. //枪口指向玩家
  51. Master.LookTargetPosition(playerPos);
  52.  
  53. //检测玩家是否在视野内
  54. if (Master.IsInTailAfterViewRange(playerPos))
  55. {
  56. IsInView = !Master.TestViewRayCast(playerPos);
  57. //关闭射线检测
  58. Master.TestViewRayCastOver();
  59. }
  60. else
  61. {
  62. IsInView = false;
  63. }
  64.  
  65. if (IsInView)
  66. {
  67. if (_pauseTimer >= 0)
  68. {
  69. Master.AnimatedSprite.Animation = AnimatorNames.Idle;
  70. _pauseTimer -= delta;
  71. }
  72. else if (_isMoveOver) //移动已经完成
  73. {
  74. RunOver(playerPos);
  75. _isMoveOver = false;
  76. }
  77. else
  78. {
  79. //计算移动
  80. var nextPos = Master.NavigationAgent2D.GetNextLocation();
  81. Master.AnimatedSprite.Animation = AnimatorNames.Run;
  82. Master.Velocity = (nextPos - Master.GlobalPosition - Master.NavigationPoint.Position).Normalized() *
  83. Master.MoveSpeed;
  84. Master.CalcMove(delta);
  85.  
  86. if (Master.NavigationAgent2D.IsNavigationFinished()) //到达终点
  87. {
  88. _pauseTimer = Utils.RandRange(0f, 0.5f);
  89. _isMoveOver = true;
  90. }
  91. else
  92. {
  93. var lastSlideCollision = Master.GetLastSlideCollision();
  94. if (lastSlideCollision != null && lastSlideCollision.Collider is Role) //碰到其他角色
  95. {
  96. _pauseTimer = Utils.RandRange(0f, 0.3f);
  97. _isMoveOver = true;
  98. }
  99. }
  100.  
  101. if (weapon != null)
  102. {
  103. var position = Master.GlobalPosition;
  104. if (position.DistanceSquaredTo(playerPos) > Mathf.Pow(Master.GetWeaponRange(0.7f), 2)) //玩家离开正常射击范围
  105. {
  106. ChangeStateLate(AiStateEnum.AiFollowUp);
  107. }
  108. else
  109. {
  110. //发起攻击
  111. Master.EnemyAttack();
  112. }
  113. }
  114. }
  115. }
  116. else //目标离开视野
  117. {
  118. ChangeStateLate(AiStateEnum.AiTailAfter);
  119. }
  120. }
  121.  
  122. private void RunOver(Vector2 targetPos)
  123. {
  124. var distance = (int)(Master.Holster.ActiveWeapon.Attribute.MinDistance * 0.7f);
  125. _nextPosition = new Vector2(
  126. targetPos.x + Utils.RandRangeInt(-distance, distance),
  127. targetPos.y + Utils.RandRangeInt(-distance, distance)
  128. );
  129. Master.NavigationAgent2D.SetTargetLocation(_nextPosition);
  130. }
  131.  
  132. public override void DebugDraw()
  133. {
  134. Master.DrawLine(new Vector2(0, -8), Master.ToLocal(_nextPosition), Colors.White);
  135. }
  136. }