Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / role / enemy / state / AiNormalState.cs
  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.  
  26. public AiNormalState() : base(AiStateEnum.AiNormal)
  27. {
  28. }
  29.  
  30. public override void Enter(AiStateEnum prev, params object[] args)
  31. {
  32. _isFindPlayer = false;
  33. _isMoveOver = true;
  34. _againstWall = false;
  35. _againstWallNormalAngle = 0;
  36. _pauseTimer = 0;
  37. }
  38.  
  39. public override void PhysicsProcess(float delta)
  40. {
  41. //其他敌人发现玩家
  42. if (Enemy.IsFindTarget)
  43. {
  44. ChangeStateLate(AiStateEnum.AiLeaveFor);
  45. return;
  46. }
  47.  
  48. if (_isFindPlayer) //已经找到玩家了
  49. {
  50. //现临时处理, 直接切换状态
  51. ChangeStateLate(AiStateEnum.AiTailAfter);
  52. }
  53. else //没有找到玩家
  54. {
  55. //检测玩家
  56. var player = GameApplication.Instance.Room.Player;
  57. //玩家中心点坐标
  58. var playerPos = player.GetCenterPosition();
  59.  
  60. if (Master.IsInViewRange(playerPos) && !Master.TestViewRayCast(playerPos)) //发现玩家
  61. {
  62. //发现玩家
  63. _isFindPlayer = true;
  64. }
  65. else if (_pauseTimer >= 0)
  66. {
  67. _pauseTimer -= delta;
  68. }
  69. else if (_isMoveOver) //没发现玩家, 且已经移动完成
  70. {
  71. RunOver();
  72. _isMoveOver = false;
  73. }
  74. else //移动中
  75. {
  76. //计算移动
  77. var nextPos = Master.NavigationAgent2D.GetNextLocation();
  78. Master.AnimatedSprite.Animation = AnimatorNames.Run;
  79. Master.Velocity = (nextPos - Master.GlobalPosition - Master.NavigationPoint.Position).Normalized() *
  80. Master.MoveSpeed;
  81. Master.CalcMove(delta);
  82.  
  83. if (Master.NavigationAgent2D.IsNavigationFinished()) //到达终点
  84. {
  85. _pauseTimer = Utils.RandRange(0.3f, 2f);
  86. _isMoveOver = true;
  87. }
  88. else
  89. {
  90. var lastSlideCollision = Master.GetLastSlideCollision();
  91. if (lastSlideCollision != null && lastSlideCollision.Collider is Role) //碰到其他角色
  92. {
  93. _pauseTimer = Utils.RandRange(0.1f, 0.5f);
  94. _isMoveOver = true;
  95. }
  96. }
  97. }
  98.  
  99. //关闭射线检测
  100. Master.TestViewRayCastOver();
  101. }
  102. }
  103.  
  104. //移动结束
  105. private void RunOver()
  106. {
  107. float angle;
  108. if (_againstWall)
  109. {
  110. angle = Utils.RandRange(_againstWallNormalAngle - Mathf.Pi * 0.5f,
  111. _againstWallNormalAngle + Mathf.Pi * 0.5f);
  112. }
  113. else
  114. {
  115. angle = Utils.RandRange(0, Mathf.Pi * 2f);
  116. }
  117.  
  118. var len = Utils.RandRangeInt(30, 200);
  119. _nextPos = new Vector2(len, 0).Rotated(angle) + Master.GlobalPosition;
  120. //获取射线碰到的坐标
  121. if (Master.TestViewRayCast(_nextPos)) //碰到墙壁
  122. {
  123. _nextPos = Master.ViewRay.GetCollisionPoint();
  124. _againstWall = true;
  125. _againstWallNormalAngle = Master.ViewRay.GetCollisionNormal().Angle();
  126. }
  127. else
  128. {
  129. _againstWall = false;
  130. }
  131.  
  132. Master.NavigationAgent2D.SetTargetLocation(_nextPos);
  133. Master.LookTargetPosition(_nextPos);
  134. }
  135.  
  136. public override void DebugDraw()
  137. {
  138. Master.DrawLine(new Vector2(0, -8), Master.ToLocal(_nextPos), Colors.Green);
  139. }
  140. }