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. public override void PhysicsProcess(float delta)
  32. {
  33. var playerPos = GameApplication.Instance.Room.Player.GetCenterPosition();
  34. //更新玩家位置
  35. if (_navigationUpdateTimer <= 0)
  36. {
  37. //每隔一段时间秒更改目标位置
  38. _navigationUpdateTimer = _navigationInterval;
  39. if (Master.NavigationAgent2D.GetTargetLocation() != playerPos)
  40. {
  41. Master.NavigationAgent2D.SetTargetLocation(playerPos);
  42. }
  43. }
  44. else
  45. {
  46. _navigationUpdateTimer -= delta;
  47. }
  48. if (!Master.NavigationAgent2D.IsNavigationFinished())
  49. {
  50. //计算移动
  51. var nextPos = Master.NavigationAgent2D.GetNextLocation();
  52. Master.LookTargetPosition(playerPos);
  53. Master.AnimatedSprite.Animation = AnimatorNames.Run;
  54. Master.Velocity = (nextPos - Master.GlobalPosition - Master.NavigationPoint.Position).Normalized() *
  55. Master.MoveSpeed;
  56. Master.CalcMove(delta);
  57. }
  58. //检测玩家是否在视野内, 如果在, 则切换到 AiTargetInView 状态
  59. if (Master.IsInTailAfterViewRange(playerPos))
  60. {
  61. if (!Master.TestViewRayCast(playerPos)) //看到玩家
  62. {
  63. //关闭射线检测
  64. Master.TestViewRayCastOver();
  65. //切换成发现目标状态
  66. ChangeStateLate(AiStateEnum.AiTargetInView);
  67. return;
  68. }
  69. else
  70. {
  71. //关闭射线检测
  72. Master.TestViewRayCastOver();
  73. }
  74. }
  75. //检测玩家是否在穿墙视野范围内, 直接检测距离即可
  76. _isInViewRange = Master.IsInViewRange(playerPos);
  77. if (_isInViewRange)
  78. {
  79. _viewTimer = 0;
  80. }
  81. else //超出视野
  82. {
  83. if (_viewTimer > 10) //10秒
  84. {
  85. ChangeStateLate(AiStateEnum.AiNormal);
  86. }
  87. else
  88. {
  89. _viewTimer += delta;
  90. }
  91. }
  92. }
  93.  
  94. public override void DebugDraw()
  95. {
  96. var playerPos = GameApplication.Instance.Room.Player.GetCenterPosition();
  97. if (_isInViewRange)
  98. {
  99. Master.DrawLine(new Vector2(0, -8), Master.ToLocal(playerPos), Colors.Orange);
  100. }
  101. else
  102. {
  103. Master.DrawLine(new Vector2(0, -8), Master.ToLocal(playerPos), Colors.Blue);
  104. }
  105. }
  106. }