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