Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / activity / role / ai / state / AiFollowUpState.cs
@小李xl 小李xl on 9 Apr 2024 4 KB 完善ai改变阵营逻辑
  1.  
  2. using System;
  3. using Godot;
  4.  
  5. namespace AiState;
  6.  
  7. /// <summary>
  8. /// 目标在视野内, 跟进目标, 如果距离在子弹有效射程内, 则开火
  9. /// </summary>
  10. public class AiFollowUpState : StateBase<AiRole, AIStateEnum>
  11. {
  12. //导航目标点刷新计时器
  13. private float _navigationUpdateTimer = 0;
  14. private float _navigationInterval = 0.3f;
  15.  
  16. public AiFollowUpState() : base(AIStateEnum.AiFollowUp)
  17. {
  18. }
  19.  
  20. public override void Enter(AIStateEnum prev, params object[] args)
  21. {
  22. if (Master.LookTarget == null)
  23. {
  24. ChangeState(AIStateEnum.AiNormal);
  25. return;
  26. //throw new Exception("进入 AIAdvancedStateEnum.AiFollowUp 状态时角色没有攻击目标!");
  27. }
  28. _navigationUpdateTimer = 0;
  29. }
  30.  
  31. public override void Process(float delta)
  32. {
  33. //先检查弹药是否打光
  34. if (Master.IsAllWeaponTotalAmmoEmpty())
  35. {
  36. //再寻找是否有可用的武器
  37. var targetWeapon = Master.FindTargetWeapon();
  38. if (targetWeapon != null)
  39. {
  40. ChangeState(AIStateEnum.AiFindAmmo, targetWeapon);
  41. return;
  42. }
  43. else
  44. {
  45. //切换到随机移动状态
  46. ChangeState(AIStateEnum.AiSurround);
  47. }
  48. }
  49.  
  50. var playerPos = Master.LookTarget.GetCenterPosition();
  51.  
  52. //更新玩家位置
  53. if (_navigationUpdateTimer <= 0)
  54. {
  55. //每隔一段时间秒更改目标位置
  56. _navigationUpdateTimer = _navigationInterval;
  57. Master.NavigationAgent2D.TargetPosition = playerPos;
  58. }
  59. else
  60. {
  61. _navigationUpdateTimer -= delta;
  62. }
  63.  
  64. //是否在攻击范围内
  65. var inAttackRange = false;
  66.  
  67. var weapon = Master.WeaponPack.ActiveItem;
  68. var distanceSquared = Master.Position.DistanceSquaredTo(playerPos);
  69. if (weapon != null)
  70. {
  71. inAttackRange = distanceSquared <= Mathf.Pow(Master.GetWeaponRange(0.7f), 2);
  72. }
  73. else
  74. {
  75. inAttackRange = distanceSquared <= Mathf.Pow(Master.ViewRange * 0.7f, 2);
  76. }
  77. if (!Master.NavigationAgent2D.IsNavigationFinished())
  78. {
  79. //移动
  80. Master.DoMove();
  81. }
  82. else
  83. {
  84. //站立
  85. Master.DoIdle();
  86. }
  87.  
  88. //在视野中
  89. if (Master.TargetInView)
  90. {
  91. //更新标记位置
  92. Master.UpdateMarkTargetPosition();
  93. if (inAttackRange) //在攻击范围内
  94. {
  95. if (weapon != null)
  96. {
  97. //距离够近, 可以切换到环绕模式
  98. if (distanceSquared <= Mathf.Pow(Utils.GetConfigRangeStart(weapon.Attribute.Bullet.DistanceRange) * 0.7f, 2))
  99. {
  100. ChangeState(AIStateEnum.AiSurround);
  101. }
  102. else if (!Master.IsAttack && weapon.TriggerIsReady()) //可以攻击
  103. {
  104. //攻击状态
  105. ChangeState(AIStateEnum.AiAttack);
  106. }
  107. }
  108. else
  109. {
  110. //距离够近, 可以切换到环绕模式
  111. if (distanceSquared <= Mathf.Pow(Master.ViewRange * 0.7f, 2))
  112. {
  113. ChangeState(AIStateEnum.AiSurround);
  114. }
  115. else if (!Master.IsAttack && Master.NoWeaponAttack) //可以在没有武器时发起攻击
  116. {
  117. //攻击状态
  118. ChangeState(AIStateEnum.AiAttack);
  119. }
  120. }
  121. }
  122. }
  123. else //不在视野中
  124. {
  125. ChangeState(AIStateEnum.AiTailAfter);
  126. }
  127. }
  128.  
  129. public override void DebugDraw()
  130. {
  131. var playerPos = Master.LookTarget.GetCenterPosition();
  132. Master.DrawLine(new Vector2(0, -8), Master.ToLocal(playerPos), Colors.Red);
  133. }
  134. }