Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / activity / role / enemy / state / AiLeaveForState.cs
  1.  
  2. using System;
  3. using Godot;
  4.  
  5. namespace EnemyState;
  6.  
  7. /// <summary>
  8. /// 收到其他敌人通知, 前往发现目标的位置
  9. /// </summary>
  10. public class AiLeaveForState : StateBase<Enemy, AIStateEnum>
  11. {
  12. //导航目标点刷新计时器
  13. private float _navigationUpdateTimer = 0;
  14. private float _navigationInterval = 0.3f;
  15.  
  16. private float _idleTimer = 0;
  17. //目标
  18. private ActivityObject _target;
  19. //目标点
  20. private Vector2 _targetPosition;
  21.  
  22. public AiLeaveForState() : base(AIStateEnum.AiLeaveFor)
  23. {
  24. }
  25.  
  26. public override void Enter(AIStateEnum prev, params object[] args)
  27. {
  28. if (args.Length == 0)
  29. {
  30. throw new Exception("进入 AINormalStateEnum.AiLeaveFor 状态必须带上目标对象");
  31. }
  32.  
  33. _target = (ActivityObject)args[0];
  34. //先检查弹药是否打光
  35. if (Master.IsAllWeaponTotalAmmoEmpty())
  36. {
  37. //再寻找是否有可用的武器
  38. var targetWeapon = Master.FindTargetWeapon();
  39. if (targetWeapon != null)
  40. {
  41. Master.LookTarget = _target;
  42. ChangeState(AIStateEnum.AiFindAmmo, targetWeapon);
  43. return;
  44. }
  45. }
  46.  
  47. _idleTimer = 1;
  48. _targetPosition = _target.GetCenterPosition();
  49. Master.LookTargetPosition(_targetPosition);
  50. Master.AnimationPlayer.Play(AnimatorNames.Query);
  51. }
  52.  
  53. public override void Exit(AIStateEnum next)
  54. {
  55. Master.AnimationPlayer.Play(AnimatorNames.Reset);
  56. }
  57.  
  58. public override void Process(float delta)
  59. {
  60. if (_idleTimer > 0)
  61. {
  62. _idleTimer -= delta;
  63. return;
  64. }
  65. //这个状态下不会有攻击事件, 所以没必要每一帧检查是否弹药耗尽
  66. //更新玩家位置
  67. if (_navigationUpdateTimer <= 0)
  68. {
  69. //每隔一段时间秒更改目标位置
  70. _navigationUpdateTimer = _navigationInterval;
  71. if (Master.AffiliationArea.RoomInfo.MarkTargetPosition.TryGetValue(_target.Id, out var pos))
  72. {
  73. _targetPosition = pos;
  74. }
  75. Master.NavigationAgent2D.TargetPosition = _targetPosition;
  76. }
  77. else
  78. {
  79. _navigationUpdateTimer -= delta;
  80. }
  81.  
  82. if (!Master.NavigationAgent2D.IsNavigationFinished())
  83. {
  84. Master.LookTargetPosition(_targetPosition);
  85. //移动
  86. Master.DoMove();
  87. }
  88. else
  89. {
  90. //站立
  91. Master.DoIdle();
  92. }
  93.  
  94. var playerPos = Player.Current.GetCenterPosition();
  95. //检测玩家是否在视野内, 如果在, 则切换到 AiTargetInView 状态
  96. if (Master.IsInTailAfterViewRange(playerPos))
  97. {
  98. if (!Master.TestViewRayCast(playerPos)) //看到玩家
  99. {
  100. //关闭射线检测
  101. Master.TestViewRayCastOver();
  102. //切换成发现目标状态
  103. Master.LookTarget = Player.Current;
  104. ChangeState(AIStateEnum.AiFollowUp);
  105. return;
  106. }
  107. else
  108. {
  109. //关闭射线检测
  110. Master.TestViewRayCastOver();
  111. }
  112. }
  113.  
  114. //移动到目标掉了, 还没发现目标
  115. if (Master.NavigationAgent2D.IsNavigationFinished())
  116. {
  117. ChangeState(AIStateEnum.AiNormal);
  118. }
  119. }
  120.  
  121. public override void DebugDraw()
  122. {
  123. Master.DrawLine(Vector2.Zero, Master.ToLocal(Master.NavigationAgent2D.TargetPosition), Colors.Yellow);
  124. }
  125. }