Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / activity / 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. ChangeState(AiStateEnum.AiFindAmmo, targetWeapon);
  38. }
  39. }
  40. }
  41. public override void Process(float delta)
  42. {
  43. //这个状态下不会有攻击事件, 所以没必要每一帧检查是否弹药耗尽
  44. var playerPos = Player.Current.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. var weapon = Master.WeaponPack.ActiveItem;
  61. if (weapon == null || !weapon.Attribute.AiAttackAttr.FiringStand ||
  62. (Master.AttackState != AiAttackState.LockingTime && Master.AttackState != AiAttackState.Attack))
  63. {
  64. //计算移动
  65. var nextPos = Master.NavigationAgent2D.GetNextPathPosition();
  66. Master.AnimatedSprite.Play(AnimatorNames.Run);
  67. Master.BasisVelocity = (nextPos - Master.GlobalPosition - Master.NavigationPoint.Position).Normalized() *
  68. Master.RoleState.MoveSpeed;
  69. }
  70. else
  71. {
  72. Master.AnimatedSprite.Play(AnimatorNames.Idle);
  73. Master.BasisVelocity = Vector2.Zero;
  74. }
  75. }
  76. else
  77. {
  78. Master.BasisVelocity = Vector2.Zero;
  79. }
  80. //检测玩家是否在视野内, 如果在, 则切换到 AiTargetInView 状态
  81. if (Master.IsInTailAfterViewRange(playerPos))
  82. {
  83. if (!Master.TestViewRayCast(playerPos)) //看到玩家
  84. {
  85. //关闭射线检测
  86. Master.TestViewRayCastOver();
  87. //切换成发现目标状态
  88. ChangeState(AiStateEnum.AiFollowUp);
  89. return;
  90. }
  91. else
  92. {
  93. //关闭射线检测
  94. Master.TestViewRayCastOver();
  95. }
  96. }
  97. //检测玩家是否在穿墙视野范围内, 直接检测距离即可
  98. _isInViewRange = Master.IsInViewRange(playerPos);
  99. if (_isInViewRange)
  100. {
  101. _viewTimer = 0;
  102. }
  103. else //超出视野
  104. {
  105. if (_viewTimer > 10) //10秒
  106. {
  107. ChangeState(AiStateEnum.AiNormal);
  108. }
  109. else
  110. {
  111. _viewTimer += delta;
  112. }
  113. }
  114. }
  115.  
  116. public override void DebugDraw()
  117. {
  118. var playerPos = Player.Current.GetCenterPosition();
  119. if (_isInViewRange)
  120. {
  121. Master.DrawLine(new Vector2(0, -8), Master.ToLocal(playerPos), Colors.Orange);
  122. }
  123. else
  124. {
  125. Master.DrawLine(new Vector2(0, -8), Master.ToLocal(playerPos), Colors.Blue);
  126. }
  127. }
  128. }