Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / activity / role / enemy / state / AiFollowUpState.cs
  1.  
  2. using Godot;
  3.  
  4. /// <summary>
  5. /// 目标在视野内, 跟进目标, 如果距离在子弹有效射程内, 则开火
  6. /// </summary>
  7. public class AiFollowUpState : StateBase<Enemy, AiStateEnum>
  8. {
  9. //导航目标点刷新计时器
  10. private float _navigationUpdateTimer = 0;
  11. private float _navigationInterval = 0.3f;
  12.  
  13. public AiFollowUpState() : base(AiStateEnum.AiFollowUp)
  14. {
  15. }
  16.  
  17. public override void Enter(AiStateEnum prev, params object[] args)
  18. {
  19. _navigationUpdateTimer = 0;
  20. Master.TargetInView = true;
  21. }
  22.  
  23. public override void Process(float delta)
  24. {
  25. //先检查弹药是否打光
  26. if (Master.IsAllWeaponTotalAmmoEmpty())
  27. {
  28. //再寻找是否有可用的武器
  29. var targetWeapon = Master.FindTargetWeapon();
  30. if (targetWeapon != null)
  31. {
  32. ChangeState(AiStateEnum.AiFindAmmo, targetWeapon);
  33. return;
  34. }
  35. else
  36. {
  37. //切换到随机移动状态
  38. ChangeState(AiStateEnum.AiSurround);
  39. }
  40. }
  41.  
  42. var playerPos = Player.Current.GetCenterPosition();
  43.  
  44. //更新玩家位置
  45. if (_navigationUpdateTimer <= 0)
  46. {
  47. //每隔一段时间秒更改目标位置
  48. _navigationUpdateTimer = _navigationInterval;
  49. Master.NavigationAgent2D.TargetPosition = playerPos;
  50. }
  51. else
  52. {
  53. _navigationUpdateTimer -= delta;
  54. }
  55.  
  56. var masterPosition = Master.GlobalPosition;
  57.  
  58. //是否在攻击范围内
  59. var inAttackRange = false;
  60.  
  61. var weapon = Master.WeaponPack.ActiveItem;
  62. if (weapon != null)
  63. {
  64. inAttackRange = masterPosition.DistanceSquaredTo(playerPos) <= Mathf.Pow(Master.GetWeaponRange(0.7f), 2);
  65. }
  66.  
  67. //枪口指向玩家
  68. Master.LookTargetPosition(playerPos);
  69. if (!Master.NavigationAgent2D.IsNavigationFinished())
  70. {
  71. if (weapon == null || !weapon.Attribute.AiAttackAttr.FiringStand ||
  72. (Master.AttackState != AiAttackState.LockingTime && Master.AttackState != AiAttackState.Attack))
  73. {
  74. //计算移动
  75. var nextPos = Master.NavigationAgent2D.GetNextPathPosition();
  76. Master.AnimatedSprite.Play(AnimatorNames.Run);
  77. Master.BasisVelocity = (nextPos - masterPosition - Master.NavigationPoint.Position).Normalized() *
  78. Master.RoleState.MoveSpeed;
  79. }
  80. else
  81. {
  82. Master.AnimatedSprite.Play(AnimatorNames.Idle);
  83. Master.BasisVelocity = Vector2.Zero;
  84. }
  85. }
  86. else
  87. {
  88. Master.BasisVelocity = Vector2.Zero;
  89. }
  90.  
  91. //检测玩家是否在视野内
  92. if (Master.IsInTailAfterViewRange(playerPos))
  93. {
  94. Master.TargetInView = !Master.TestViewRayCast(playerPos);
  95. //关闭射线检测
  96. Master.TestViewRayCastOver();
  97. }
  98. else
  99. {
  100. Master.TargetInView = false;
  101. }
  102.  
  103. //在视野中, 或者锁敌状态下, 或者攻击状态下, 继续保持原本逻辑
  104. if (Master.TargetInView || Master.AttackState == AiAttackState.LockingTime || Master.AttackState == AiAttackState.Attack)
  105. {
  106. if (inAttackRange) //在攻击范围内
  107. {
  108. //发起攻击
  109. Master.EnemyAttack();
  110. //距离够近, 可以切换到环绕模式
  111. if (Master.GlobalPosition.DistanceSquaredTo(playerPos) <= Mathf.Pow(Utils.GetConfigRangeStart(weapon.Attribute.Bullet.DistanceRange), 2) * 0.7f)
  112. {
  113. ChangeState(AiStateEnum.AiSurround);
  114. }
  115. }
  116. }
  117. else //不在视野中
  118. {
  119. ChangeState(AiStateEnum.AiTailAfter);
  120. }
  121. }
  122.  
  123. public override void DebugDraw()
  124. {
  125. var playerPos = Player.Current.GetCenterPosition();
  126. Master.DrawLine(new Vector2(0, -8), Master.ToLocal(playerPos), Colors.Red);
  127. }
  128. }