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 Process(float delta)
  30. {
  31. //先检查弹药是否打光
  32. if (Master.IsAllWeaponTotalAmmoEmpty())
  33. {
  34. //再寻找是否有可用的武器
  35. if (Master.CheckUsableWeaponInUnclaimed())
  36. {
  37. //切换到寻找武器状态
  38. ChangeStateLate(AiStateEnum.AiFindAmmo);
  39. return;
  40. }
  41. else
  42. {
  43. //切换到随机移动状态
  44. ChangeStateLate(AiStateEnum.AiSurround);
  45. }
  46. }
  47. var playerPos = Player.Current.GetCenterPosition();
  48.  
  49. //更新玩家位置
  50. if (_navigationUpdateTimer <= 0)
  51. {
  52. //每隔一段时间秒更改目标位置
  53. _navigationUpdateTimer = _navigationInterval;
  54. Master.NavigationAgent2D.TargetPosition = playerPos;
  55. }
  56. else
  57. {
  58. _navigationUpdateTimer -= delta;
  59. }
  60.  
  61. var masterPosition = Master.GlobalPosition;
  62.  
  63. //是否在攻击范围内
  64. var inAttackRange = false;
  65.  
  66. var weapon = Master.Holster.ActiveWeapon;
  67. if (weapon != null)
  68. {
  69. inAttackRange = masterPosition.DistanceSquaredTo(playerPos) <= Mathf.Pow(Master.GetWeaponRange(0.7f), 2);
  70. }
  71.  
  72. //枪口指向玩家
  73. Master.LookTargetPosition(playerPos);
  74. if (!Master.NavigationAgent2D.IsNavigationFinished())
  75. {
  76. //计算移动
  77. var nextPos = Master.NavigationAgent2D.GetNextPathPosition();
  78. Master.AnimatedSprite.Play(AnimatorNames.Run);
  79. Master.BasisVelocity = (nextPos - masterPosition - Master.NavigationPoint.Position).Normalized() *
  80. Master.MoveSpeed;
  81. }
  82. else
  83. {
  84. Master.BasisVelocity = Vector2.Zero;
  85. }
  86.  
  87. //检测玩家是否在视野内
  88. if (Master.IsInTailAfterViewRange(playerPos))
  89. {
  90. IsInView = !Master.TestViewRayCast(playerPos);
  91. //关闭射线检测
  92. Master.TestViewRayCastOver();
  93. }
  94. else
  95. {
  96. IsInView = false;
  97. }
  98.  
  99. if (IsInView)
  100. {
  101. if (inAttackRange) //在攻击范围内
  102. {
  103. //发起攻击
  104. Master.EnemyAttack(delta);
  105. //距离够近, 可以切换到环绕模式
  106. if (Master.GlobalPosition.DistanceSquaredTo(playerPos) <= Mathf.Pow(weapon.Attribute.MinDistance, 2) * 0.7f)
  107. {
  108. ChangeStateLate(AiStateEnum.AiSurround);
  109. }
  110. }
  111. }
  112. else
  113. {
  114. ChangeStateLate(AiStateEnum.AiTailAfter);
  115. }
  116. }
  117.  
  118. public override void DebugDraw()
  119. {
  120. var playerPos = GameApplication.Instance.RoomManager.Player.GetCenterPosition();
  121. Master.DrawLine(new Vector2(0, -8), Master.ToLocal(playerPos), Colors.Red);
  122. }
  123. }