Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / activity / role / enemy / advancedState / AiNormalState.cs
  1.  
  2. using Godot;
  3.  
  4. namespace AdvancedState;
  5.  
  6. /// <summary>
  7. /// AI 正常状态
  8. /// </summary>
  9. public class AiNormalState : StateBase<AdvancedEnemy, AIAdvancedStateEnum>
  10. {
  11. //下一个运动的坐标
  12. private Vector2 _nextPos;
  13.  
  14. //是否移动结束
  15. private bool _isMoveOver;
  16.  
  17. //上一次移动是否撞墙
  18. private bool _againstWall;
  19. //撞墙法线角度
  20. private float _againstWallNormalAngle;
  21.  
  22. //移动停顿计时器
  23. private float _pauseTimer;
  24. private bool _moveFlag;
  25.  
  26. //上一帧位置
  27. private Vector2 _prevPos;
  28. //卡在一个位置的时间
  29. private float _lockTimer;
  30.  
  31. public AiNormalState() : base(AIAdvancedStateEnum.AiNormal)
  32. {
  33. }
  34.  
  35. public override void Enter(AIAdvancedStateEnum prev, params object[] args)
  36. {
  37. _isMoveOver = true;
  38. _againstWall = false;
  39. _againstWallNormalAngle = 0;
  40. _pauseTimer = 0;
  41. _moveFlag = false;
  42. Master.LookTarget = null;
  43. }
  44.  
  45. public override void Process(float delta)
  46. {
  47. //检测玩家
  48. var player = Player.Current;
  49. //玩家中心点坐标
  50. var playerPos = player.GetCenterPosition();
  51.  
  52. if (Master.IsInViewRange(playerPos) && !Master.TestViewRayCast(playerPos)) //发现玩家
  53. {
  54. //发现玩家
  55. Master.LookTarget = player;
  56. //进入惊讶状态, 然后再进入通知状态
  57. ChangeState(AIAdvancedStateEnum.AiAstonished, AIAdvancedStateEnum.AiNotify);
  58. return;
  59. }
  60. else if (_pauseTimer >= 0)
  61. {
  62. Master.AnimatedSprite.Play(AnimatorNames.Idle);
  63. _pauseTimer -= delta;
  64. }
  65. else if (_isMoveOver) //没发现玩家, 且已经移动完成
  66. {
  67. RunOver();
  68. _isMoveOver = false;
  69. }
  70. else //移动中
  71. {
  72. if (_lockTimer >= 1) //卡在一个点超过一秒
  73. {
  74. RunOver();
  75. _isMoveOver = false;
  76. _lockTimer = 0;
  77. }
  78. else if (Master.NavigationAgent2D.IsNavigationFinished()) //到达终点
  79. {
  80. _pauseTimer = Utils.Random.RandomRangeFloat(0.3f, 2f);
  81. _isMoveOver = true;
  82. _moveFlag = false;
  83. //站立
  84. Master.DoIdle();
  85. }
  86. else if (!_moveFlag)
  87. {
  88. _moveFlag = true;
  89. var pos = Master.Position;
  90. //移动
  91. Master.DoMove();
  92. _prevPos = pos;
  93. }
  94. else
  95. {
  96. var pos = Master.Position;
  97. var lastSlideCollision = Master.GetLastSlideCollision();
  98. if (lastSlideCollision != null && lastSlideCollision.GetCollider() is AdvancedRole) //碰到其他角色
  99. {
  100. _pauseTimer = Utils.Random.RandomRangeFloat(0.1f, 0.5f);
  101. _isMoveOver = true;
  102. _moveFlag = false;
  103. //站立
  104. Master.DoIdle();
  105. }
  106. else
  107. {
  108. //移动
  109. Master.DoMove();
  110. }
  111.  
  112. if (_prevPos.DistanceSquaredTo(pos) <= 0.01f)
  113. {
  114. _lockTimer += delta;
  115. }
  116. else
  117. {
  118. _prevPos = pos;
  119. }
  120. }
  121. }
  122.  
  123. //关闭射线检测
  124. Master.TestViewRayCastOver();
  125. }
  126.  
  127. //移动结束
  128. private void RunOver()
  129. {
  130. float angle;
  131. if (_againstWall)
  132. {
  133. angle = Utils.Random.RandomRangeFloat(_againstWallNormalAngle - Mathf.Pi * 0.5f,
  134. _againstWallNormalAngle + Mathf.Pi * 0.5f);
  135. }
  136. else
  137. {
  138. angle = Utils.Random.RandomRangeFloat(0, Mathf.Pi * 2f);
  139. }
  140.  
  141. var len = Utils.Random.RandomRangeInt(30, 200);
  142. _nextPos = new Vector2(len, 0).Rotated(angle) + Master.GlobalPosition;
  143. //获取射线碰到的坐标
  144. if (Master.TestViewRayCast(_nextPos)) //碰到墙壁
  145. {
  146. _nextPos = Master.ViewRay.GetCollisionPoint();
  147. _againstWall = true;
  148. _againstWallNormalAngle = Master.ViewRay.GetCollisionNormal().Angle();
  149. }
  150. else
  151. {
  152. _againstWall = false;
  153. }
  154.  
  155. Master.NavigationAgent2D.TargetPosition = _nextPos;
  156. Master.LookTargetPosition(_nextPos);
  157. }
  158.  
  159. public override void DebugDraw()
  160. {
  161. Master.DrawLine(new Vector2(0, -8), Master.ToLocal(_nextPos), Colors.Green);
  162. }
  163. }