Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / role / enemy / state / AiFollowUpState.cs
  1.  
  2. using Godot;
  3.  
  4. /// <summary>
  5. /// 目标在视野内, 跟进目标, 如果距离在子弹有效射程内, 则开火
  6. /// </summary>
  7. public class AiFollowUpState : StateBase<Enemy, AiStateEnum>
  8. {
  9.  
  10. /// <summary>
  11. /// 目标是否在视野内
  12. /// </summary>
  13. public bool IsInView;
  14.  
  15. //导航目标点刷新计时器
  16. private float _navigationUpdateTimer = 0;
  17. private float _navigationInterval = 0.3f;
  18.  
  19. public AiFollowUpState() : base(AiStateEnum.AiFollowUp)
  20. {
  21. }
  22.  
  23. public override void Enter(AiStateEnum prev, params object[] args)
  24. {
  25. _navigationUpdateTimer = 0;
  26. IsInView = true;
  27. }
  28.  
  29. public override void PhysicsProcess(float delta)
  30. {
  31. //先检查弹药是否打光
  32. if (Master.IsAllWeaponTotalAmmoEmpty())
  33. {
  34. //再寻找是否有可用的武器
  35. if (Master.CheckUsableWeaponInUnclaimed())
  36. {
  37. //切换到寻找武器状态
  38. ChangeStateLate(AiStateEnum.AiFindAmmo);
  39. return;
  40. }
  41. }
  42. var playerPos = Player.Current.GetCenterPosition();
  43.  
  44. //更新玩家位置
  45. if (_navigationUpdateTimer <= 0)
  46. {
  47. //每隔一段时间秒更改目标位置
  48. _navigationUpdateTimer = _navigationInterval;
  49. if (Master.NavigationAgent2D.GetTargetLocation() != playerPos)
  50. {
  51. Master.NavigationAgent2D.SetTargetLocation(playerPos);
  52. }
  53. }
  54. else
  55. {
  56. _navigationUpdateTimer -= delta;
  57. }
  58.  
  59. var masterPosition = Master.GlobalPosition;
  60.  
  61. //是否在攻击范围内
  62. var inAttackRange = false;
  63.  
  64. var weapon = Master.Holster.ActiveWeapon;
  65. if (weapon != null)
  66. {
  67. inAttackRange = masterPosition.DistanceSquaredTo(playerPos) <= Mathf.Pow(Master.GetWeaponRange(0.7f), 2);
  68. }
  69.  
  70. //枪口指向玩家
  71. Master.LookTargetPosition(playerPos);
  72. if (!Master.NavigationAgent2D.IsNavigationFinished())
  73. {
  74. //计算移动
  75. var nextPos = Master.NavigationAgent2D.GetNextLocation();
  76. Master.AnimatedSprite.Animation = AnimatorNames.Run;
  77. Master.BasisVelocity = (nextPos - masterPosition - Master.NavigationPoint.Position).Normalized() *
  78. Master.MoveSpeed;
  79. }
  80. else
  81. {
  82. Master.BasisVelocity = Vector2.Zero;
  83. }
  84.  
  85. //检测玩家是否在视野内
  86. if (Master.IsInTailAfterViewRange(playerPos))
  87. {
  88. IsInView = !Master.TestViewRayCast(playerPos);
  89. //关闭射线检测
  90. Master.TestViewRayCastOver();
  91. }
  92. else
  93. {
  94. IsInView = false;
  95. }
  96.  
  97. if (IsInView)
  98. {
  99. if (inAttackRange) //在攻击范围内
  100. {
  101. //发起攻击
  102. Master.EnemyAttack();
  103. //距离够近, 可以切换到环绕模式
  104. if (Master.GlobalPosition.DistanceSquaredTo(playerPos) <= Mathf.Pow(weapon.Attribute.MinDistance, 2) * 0.7f)
  105. {
  106. ChangeStateLate(AiStateEnum.AiSurround);
  107. }
  108. }
  109. }
  110. else
  111. {
  112. ChangeStateLate(AiStateEnum.AiTailAfter);
  113. }
  114. }
  115.  
  116. public override void DebugDraw()
  117. {
  118. var playerPos = GameApplication.Instance.Room.Player.GetCenterPosition();
  119. Master.DrawLine(new Vector2(0, -8), Master.ToLocal(playerPos), Colors.Red);
  120. }
  121. }