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