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. Master.NavigationAgent2D.TargetPosition = playerPos;
  50. }
  51. else
  52. {
  53. _navigationUpdateTimer -= delta;
  54. }
  55.  
  56. var masterPosition = Master.GlobalPosition;
  57.  
  58. //是否在攻击范围内
  59. var inAttackRange = false;
  60.  
  61. var weapon = Master.Holster.ActiveWeapon;
  62. if (weapon != null)
  63. {
  64. inAttackRange = masterPosition.DistanceSquaredTo(playerPos) <= Mathf.Pow(Master.GetWeaponRange(0.7f), 2);
  65. }
  66.  
  67. //枪口指向玩家
  68. Master.LookTargetPosition(playerPos);
  69. if (!Master.NavigationAgent2D.IsNavigationFinished())
  70. {
  71. //计算移动
  72. var nextPos = Master.NavigationAgent2D.GetNextPathPosition();
  73. Master.AnimatedSprite.Animation = AnimatorNames.Run;
  74. Master.BasisVelocity = (nextPos - masterPosition - Master.NavigationPoint.Position).Normalized() *
  75. Master.MoveSpeed;
  76. }
  77. else
  78. {
  79. Master.BasisVelocity = Vector2.Zero;
  80. }
  81.  
  82. //检测玩家是否在视野内
  83. if (Master.IsInTailAfterViewRange(playerPos))
  84. {
  85. IsInView = !Master.TestViewRayCast(playerPos);
  86. //关闭射线检测
  87. Master.TestViewRayCastOver();
  88. }
  89. else
  90. {
  91. IsInView = false;
  92. }
  93.  
  94. if (IsInView)
  95. {
  96. if (inAttackRange) //在攻击范围内
  97. {
  98. //发起攻击
  99. Master.EnemyAttack();
  100. //距离够近, 可以切换到环绕模式
  101. if (Master.GlobalPosition.DistanceSquaredTo(playerPos) <= Mathf.Pow(weapon.Attribute.MinDistance, 2) * 0.7f)
  102. {
  103. ChangeStateLate(AiStateEnum.AiSurround);
  104. }
  105. }
  106. }
  107. else
  108. {
  109. ChangeStateLate(AiStateEnum.AiTailAfter);
  110. }
  111. }
  112.  
  113. public override void DebugDraw()
  114. {
  115. var playerPos = GameApplication.Instance.RoomManager.Player.GetCenterPosition();
  116. Master.DrawLine(new Vector2(0, -8), Master.ToLocal(playerPos), Colors.Red);
  117. }
  118. }