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