Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / activity / role / enemy / state / AiAttackState.cs
@小李xl 小李xl on 18 Nov 2023 8 KB 优化状态机
  1. using System;
  2. using Godot;
  3.  
  4. namespace EnemyState;
  5.  
  6. /// <summary>
  7. /// ai 攻击状态
  8. /// </summary>
  9. public class AiAttackState : StateBase<Enemy, AIStateEnum>
  10. {
  11. /// <summary>
  12. /// 上一个状态
  13. /// </summary>
  14. public AIStateEnum PrevState;
  15.  
  16. /// <summary>
  17. /// 攻击状态
  18. /// </summary>
  19. public AiAttackEnum AttackState;
  20.  
  21. //是否移动结束
  22. private bool _isMoveOver;
  23.  
  24. //移动停顿计时器
  25. private float _pauseTimer;
  26. private bool _moveFlag;
  27. //下一个移动点
  28. private Vector2 _nextPosition;
  29. //上一帧位置
  30. private Vector2 _prevPos;
  31. //卡在一个位置的时间
  32. private float _lockTimer;
  33. //进入状态的时候是否有武器
  34. private bool _hasWeapon = true;
  35. public AiAttackState() : base(AIStateEnum.AiAttack)
  36. {
  37. }
  38.  
  39. public override void Enter(AIStateEnum prev, params object[] args)
  40. {
  41. if (Master.LookTarget == null)
  42. {
  43. throw new Exception("进入 AIAdvancedStateEnum.AiAttack 状态时角色没有攻击目标!");
  44. }
  45. var weapon = Master.WeaponPack.ActiveItem;
  46.  
  47. if (weapon != null)
  48. {
  49. _hasWeapon = true;
  50. if (!weapon.TriggerIsReady())
  51. {
  52. throw new Exception("进入 AIAdvancedStateEnum.AiAttack 状态时角色武器还无法触动扳机!");
  53. }
  54. }
  55. else
  56. {
  57. _hasWeapon = false;
  58. if (Master.IsAttack)
  59. {
  60. throw new Exception("进入 AIAdvancedStateEnum.AiAttack 状态时角色攻击状态还没准备好");
  61. }
  62. }
  63. Master.BasisVelocity = Vector2.Zero;
  64. AttackState = AiAttackEnum.None;
  65. Master.LockTargetTime = 0;
  66. PrevState = prev;
  67. _isMoveOver = true;
  68. _pauseTimer = 0;
  69. _moveFlag = false;
  70. }
  71.  
  72. public override void Exit(AIStateEnum next)
  73. {
  74. Master.MountLookTarget = true;
  75. Master.LockTargetTime = 0;
  76. }
  77.  
  78. public override void Process(float delta)
  79. {
  80. //更新标记位置
  81. Master.UpdateMarkTargetPosition();
  82.  
  83. if (_hasWeapon)
  84. {
  85. WeaponRoleProcess(delta);
  86. }
  87. else
  88. {
  89. NoWeaponRoleProcess(delta);
  90. }
  91. }
  92.  
  93. //有武器的敌人更新逻辑
  94. private void WeaponRoleProcess(float delta)
  95. {
  96. var weapon = Master.WeaponPack.ActiveItem;
  97. if (weapon == null)
  98. {
  99. //攻击结束
  100. ChangeState(PrevState);
  101. }
  102. else if (AttackState == AiAttackEnum.AttackInterval) //攻击完成
  103. {
  104. if (weapon.GetAttackTimer() <= 0) //攻击冷却完成
  105. {
  106. Master.MountLookTarget = true;
  107. //这里要做换弹判断, 还有上膛判断
  108. if (weapon.CurrAmmo <= 0) //换弹判断
  109. {
  110. if (!weapon.Reloading)
  111. {
  112. weapon.Reload();
  113. }
  114. }
  115. else if (weapon.GetBeLoadedStateState() != 2) //上膛
  116. {
  117. if (weapon.GetBeLoadedStateState() == 0)
  118. {
  119. weapon.BeLoaded();
  120. }
  121. }
  122. else
  123. {
  124. //攻击结束
  125. ChangeState(PrevState);
  126. }
  127. }
  128. MoveHandler(delta);
  129. }
  130. else //攻击状态
  131. {
  132. //触发扳机
  133. AttackState = weapon.AiTriggerAttackState();
  134.  
  135. if (AttackState == AiAttackEnum.LockingTime) //锁定玩家状态
  136. {
  137. Master.LockTargetTime += delta;
  138.  
  139. var aiLockRemainderTime = Master.GetLockRemainderTime();
  140. Master.MountLookTarget = aiLockRemainderTime >= weapon.Attribute.AiAttackAttr.LockAngleTime;
  141. //更新瞄准辅助线
  142. if (weapon.Attribute.AiAttackAttr.ShowSubline)
  143. {
  144. if (Master.SubLine == null)
  145. {
  146. Master.InitSubLine();
  147. }
  148. else
  149. {
  150. Master.SubLine.Enable = true;
  151. }
  152.  
  153. //播放警告删掉动画
  154. if (!Master.SubLine.IsPlayWarnAnimation && aiLockRemainderTime <= 0.5f)
  155. {
  156. Master.SubLine.PlayWarnAnimation(0.5f);
  157. }
  158. }
  159. if (weapon.Attribute.AiAttackAttr.LockingStand) //锁定目标时站立不动
  160. {
  161. Master.DoIdle();
  162. }
  163. else //正常移动
  164. {
  165. MoveHandler(delta);
  166. }
  167. }
  168. else
  169. {
  170. Master.LockTargetTime = 0;
  171. //关闭辅助线
  172. if (Master.SubLine != null)
  173. {
  174. Master.SubLine.Enable = false;
  175. }
  176.  
  177. if (AttackState == AiAttackEnum.Attack || AttackState == AiAttackEnum.AttackInterval)
  178. {
  179. if (weapon.Attribute.AiAttackAttr.AttackLockAngle) //开火时锁定枪口角度
  180. {
  181. //连发状态锁定角度
  182. Master.MountLookTarget = !(weapon.GetContinuousCount() > 0 || weapon.GetAttackTimer() > 0);
  183. }
  184. else
  185. {
  186. Master.MountLookTarget = true;
  187. }
  188. }
  189. else
  190. {
  191. Master.MountLookTarget = true;
  192. }
  193. if (AttackState == AiAttackEnum.Attack && weapon.Attribute.AiAttackAttr.FiringStand) //开火时站立不动
  194. {
  195. Master.DoIdle();
  196. }
  197. else //正常移动
  198. {
  199. MoveHandler(delta);
  200. }
  201. }
  202. }
  203. }
  204.  
  205. //没有武器的敌人攻击逻辑
  206. private void NoWeaponRoleProcess(float delta)
  207. {
  208. var weapon = Master.WeaponPack.ActiveItem;
  209. if (weapon != null)
  210. {
  211. //找到武器了, 攻击结束
  212. ChangeState(PrevState);
  213. }
  214. else if (AttackState == AiAttackEnum.AttackInterval) //攻击结束
  215. {
  216. }
  217. else //攻击状态
  218. {
  219. Master.Attack();
  220. }
  221. }
  222. private void MoveHandler(float delta)
  223. {
  224.  
  225. if (_pauseTimer >= 0)
  226. {
  227. Master.AnimatedSprite.Play(AnimatorNames.Idle);
  228. _pauseTimer -= delta;
  229. }
  230. else if (_isMoveOver) //移动已经完成
  231. {
  232. RunOver(Master.LookTarget.Position);
  233. _isMoveOver = false;
  234. }
  235. else
  236. {
  237. var masterPosition = Master.Position;
  238. if (_lockTimer >= 1) //卡在一个点超过一秒
  239. {
  240. RunOver(Master.LookTarget.Position);
  241. _isMoveOver = false;
  242. _lockTimer = 0;
  243. }
  244. else if (Master.NavigationAgent2D.IsNavigationFinished()) //到达终点
  245. {
  246. _pauseTimer = Utils.Random.RandomRangeFloat(0f, 0.5f);
  247. _isMoveOver = true;
  248. _moveFlag = false;
  249. //站立
  250. Master.DoIdle();
  251. }
  252. else if (!_moveFlag)
  253. {
  254. _moveFlag = true;
  255. //移动
  256. Master.DoMove();
  257. }
  258. else
  259. {
  260. var lastSlideCollision = Master.GetLastSlideCollision();
  261. if (lastSlideCollision != null && lastSlideCollision.GetCollider() is Role) //碰到其他角色
  262. {
  263. _pauseTimer = Utils.Random.RandomRangeFloat(0f, 0.3f);
  264. _isMoveOver = true;
  265. _moveFlag = false;
  266. //站立
  267. Master.DoIdle();
  268. }
  269. else
  270. {
  271. //移动
  272. Master.DoMove();
  273. }
  274.  
  275. if (_prevPos.DistanceSquaredTo(masterPosition) <= 1 * delta)
  276. {
  277. _lockTimer += delta;
  278. }
  279. else
  280. {
  281. _lockTimer = 0;
  282. _prevPos = masterPosition;
  283. }
  284. }
  285. }
  286. }
  287.  
  288. private void RunOver(Vector2 targetPos)
  289. {
  290. var weapon = Master.WeaponPack.ActiveItem;
  291. var distance = (int)(weapon == null ? 150 : (Utils.GetConfigRangeStart(weapon.Attribute.Bullet.DistanceRange) * 0.7f));
  292. _nextPosition = new Vector2(
  293. targetPos.X + Utils.Random.RandomRangeInt(-distance, distance),
  294. targetPos.Y + Utils.Random.RandomRangeInt(-distance, distance)
  295. );
  296. Master.NavigationAgent2D.TargetPosition = _nextPosition;
  297. }
  298. }