Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / role / enemy / state / AiTailAfterState.cs
  1.  
  2. using Godot;
  3.  
  4. /// <summary>
  5. /// AI 发现玩家, 跟随玩家
  6. /// </summary>
  7. public class AiTailAfterState : StateBase<Enemy, AiStateEnum>
  8. {
  9. /// <summary>
  10. /// 目标是否在视野半径内
  11. /// </summary>
  12. private bool _isInViewRange;
  13.  
  14. //导航目标点刷新计时器
  15. private float _navigationUpdateTimer = 0;
  16. private float _navigationInterval = 0.3f;
  17.  
  18. //目标从视野消失时已经过去的时间
  19. private float _viewTimer;
  20.  
  21. public AiTailAfterState() : base(AiStateEnum.AiTailAfter)
  22. {
  23. }
  24.  
  25. public override void Enter(AiStateEnum prev, params object[] args)
  26. {
  27. _isInViewRange = true;
  28. _navigationUpdateTimer = 0;
  29. _viewTimer = 0;
  30. //先检查弹药是否打光
  31. if (Master.IsAllWeaponTotalAmmoEmpty())
  32. {
  33. //再寻找是否有可用的武器
  34. var targetWeapon = Master.FindTargetWeapon();
  35. if (targetWeapon != null)
  36. {
  37. ChangeStateLate(AiStateEnum.AiFindAmmo, targetWeapon);
  38. }
  39. }
  40. }
  41. public override void Process(float delta)
  42. {
  43. //这个状态下不会有攻击事件, 所以没必要每一帧检查是否弹药耗尽
  44. var playerPos = GameApplication.Instance.RoomManager.Player.GetCenterPosition();
  45. //更新玩家位置
  46. if (_navigationUpdateTimer <= 0)
  47. {
  48. //每隔一段时间秒更改目标位置
  49. _navigationUpdateTimer = _navigationInterval;
  50. Master.NavigationAgent2D.TargetPosition = playerPos;
  51. }
  52. else
  53. {
  54. _navigationUpdateTimer -= delta;
  55. }
  56. //枪口指向玩家
  57. Master.LookTargetPosition(playerPos);
  58. if (!Master.NavigationAgent2D.IsNavigationFinished())
  59. {
  60. //计算移动
  61. var nextPos = Master.NavigationAgent2D.GetNextPathPosition();
  62. Master.AnimatedSprite.Play(AnimatorNames.Run);
  63. Master.BasisVelocity = (nextPos - Master.GlobalPosition - Master.NavigationPoint.Position).Normalized() *
  64. Master.MoveSpeed;
  65. }
  66. else
  67. {
  68. Master.BasisVelocity = Vector2.Zero;
  69. }
  70. //检测玩家是否在视野内, 如果在, 则切换到 AiTargetInView 状态
  71. if (Master.IsInTailAfterViewRange(playerPos))
  72. {
  73. if (!Master.TestViewRayCast(playerPos)) //看到玩家
  74. {
  75. //关闭射线检测
  76. Master.TestViewRayCastOver();
  77. //切换成发现目标状态
  78. ChangeStateLate(AiStateEnum.AiFollowUp);
  79. return;
  80. }
  81. else
  82. {
  83. //关闭射线检测
  84. Master.TestViewRayCastOver();
  85. }
  86. }
  87. //检测玩家是否在穿墙视野范围内, 直接检测距离即可
  88. _isInViewRange = Master.IsInViewRange(playerPos);
  89. if (_isInViewRange)
  90. {
  91. _viewTimer = 0;
  92. }
  93. else //超出视野
  94. {
  95. if (_viewTimer > 10) //10秒
  96. {
  97. ChangeStateLate(AiStateEnum.AiNormal);
  98. }
  99. else
  100. {
  101. _viewTimer += delta;
  102. }
  103. }
  104. }
  105.  
  106. public override void DebugDraw()
  107. {
  108. var playerPos = GameApplication.Instance.RoomManager.Player.GetCenterPosition();
  109. if (_isInViewRange)
  110. {
  111. Master.DrawLine(new Vector2(0, -8), Master.ToLocal(playerPos), Colors.Orange);
  112. }
  113. else
  114. {
  115. Master.DrawLine(new Vector2(0, -8), Master.ToLocal(playerPos), Colors.Blue);
  116. }
  117. }
  118. }