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