Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / activity / role / ai / state / AiTailAfterState.cs
@小李xl 小李xl on 10 Apr 2024 3 KB 继续完善Ai改变阵营逻辑
  1.  
  2. using System;
  3. using Godot;
  4.  
  5. namespace AiState;
  6.  
  7. /// <summary>
  8. /// AI 发现玩家, 跟随玩家, 但是不在视野范围内
  9. /// </summary>
  10. public class AiTailAfterState : StateBase<AiRole, AIStateEnum>
  11. {
  12. /// <summary>
  13. /// 目标是否在视野半径内
  14. /// </summary>
  15. private bool _isInViewRange;
  16.  
  17. //导航目标点刷新计时器
  18. private float _navigationUpdateTimer = 0;
  19. private float _navigationInterval = 0.3f;
  20.  
  21. //目标从视野消失时已经过去的时间
  22. private float _viewTimer;
  23.  
  24. public AiTailAfterState() : base(AIStateEnum.AiTailAfter)
  25. {
  26. }
  27.  
  28. public override void Enter(AIStateEnum prev, params object[] args)
  29. {
  30. if (Master.LookTarget == null)
  31. {
  32. ChangeState(AIStateEnum.AiNormal);
  33. return;
  34. //throw new Exception("进入 AIAdvancedStateEnum.AiTailAfter 状态时角色没有攻击目标!");
  35. }
  36. _isInViewRange = true;
  37. _navigationUpdateTimer = 0;
  38. _viewTimer = 0;
  39. //先检查弹药是否打光
  40. if (Master.IsAllWeaponTotalAmmoEmpty())
  41. {
  42. //再寻找是否有可用的武器
  43. var targetWeapon = Master.FindTargetWeapon();
  44. if (targetWeapon != null)
  45. {
  46. ChangeState(AIStateEnum.AiFindAmmo, targetWeapon);
  47. }
  48. }
  49. }
  50.  
  51. public override void Process(float delta)
  52. {
  53. //这个状态下不会有攻击事件, 所以没必要每一帧检查是否弹药耗尽
  54.  
  55. var target = Master.GetAttackTarget();
  56. if (target == null)
  57. {
  58. Master.LookTarget = null;
  59. ChangeState(AIStateEnum.AiNormal);
  60. return;
  61. }
  62.  
  63. Master.LookTarget = target;
  64. var playerPos = target.GetCenterPosition();
  65. //更新玩家位置
  66. if (_navigationUpdateTimer <= 0)
  67. {
  68. //每隔一段时间秒更改目标位置
  69. _navigationUpdateTimer = _navigationInterval;
  70. Master.NavigationAgent2D.TargetPosition = playerPos;
  71. }
  72. else
  73. {
  74. _navigationUpdateTimer -= delta;
  75. }
  76. if (!Master.NavigationAgent2D.IsNavigationFinished())
  77. {
  78. //移动
  79. Master.DoMove();
  80. }
  81. else
  82. {
  83. //站立
  84. Master.DoIdle();
  85. }
  86. //检测玩家是否在视野内
  87. if (!Master.TargetHasOcclusion) //直接看到玩家
  88. {
  89. //切换成发现目标状态
  90. ChangeState(AIStateEnum.AiFollowUp);
  91. return;
  92. }
  93. //检测玩家是否在穿墙视野范围内, 直接检测距离即可
  94. _isInViewRange = Master.TargetInViewRange;
  95. if (_isInViewRange)
  96. {
  97. _viewTimer = 0;
  98. }
  99. else //超出视野
  100. {
  101. if (_viewTimer > 10) //10秒
  102. {
  103. ChangeState(AIStateEnum.AiNormal);
  104. }
  105. else
  106. {
  107. _viewTimer += delta;
  108. }
  109. }
  110. }
  111.  
  112. public override void DebugDraw()
  113. {
  114. var playerPos = Master.LookTarget.GetCenterPosition();
  115. if (_isInViewRange)
  116. {
  117. Master.DrawLine(new Vector2(0, -8), Master.ToLocal(playerPos), Colors.Orange);
  118. }
  119. else
  120. {
  121. Master.DrawLine(new Vector2(0, -8), Master.ToLocal(playerPos), Colors.Blue);
  122. }
  123. }
  124. }