Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / activity / role / enemy / Boss.cs
  1.  
  2. using System;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using System.Linq;
  6. using Config;
  7. using Godot;
  8.  
  9. /// <summary>
  10. /// Boss逻辑类
  11. /// </summary>
  12. [Tool]
  13. public partial class Boss : AiRole
  14. {
  15. private long _attaclCoroutine = -1;
  16. private List<Vector2> _vertices;
  17. private float _targetRotation;
  18.  
  19. private int state = 0;
  20.  
  21. public override void OnInit()
  22. {
  23. base.OnInit();
  24. WeaponPack.SetCapacity(0);
  25. Camp = CampEnum.Camp2;
  26. NoWeaponAttack = true;
  27. MountLookTarget = true;
  28. FiringStand = true;
  29.  
  30. MaxHp = 2000;
  31. Hp = MaxHp;
  32.  
  33. AnimatedSprite.Visible = false;
  34. StateController.Enable = false;
  35. }
  36.  
  37. protected override RoleState OnCreateRoleState()
  38. {
  39. var roleState = base.OnCreateRoleState();
  40. roleState.MoveSpeed = 45;
  41. return roleState;
  42. }
  43.  
  44. protected override void Process(float delta)
  45. {
  46. if (Hp <= 0)
  47. {
  48. return;
  49. }
  50. base.Process(delta);
  51. LookTarget = World.Player;
  52. ViewArea.LookAt(LookTarget.Position);
  53. //UpdateFace();
  54.  
  55. var velocity = BasisVelocity;
  56. if ((Face == FaceDirection.Right && velocity.X > 0) || (Face == FaceDirection.Left && velocity.X < 0))
  57. {
  58. _targetRotation = 10;
  59. }
  60. else if ((Face == FaceDirection.Right && velocity.X < 0) || (Face == FaceDirection.Left && velocity.X > 0))
  61. {
  62. _targetRotation = -10;
  63. }
  64. else
  65. {
  66. _targetRotation = 0;
  67. }
  68.  
  69. AnimatedSprite.RotationDegrees = Mathf.MoveToward(AnimatedSprite.RotationDegrees, _targetRotation, 25 * delta);
  70. }
  71.  
  72. public override void HurtHandler(ActivityObject target, int damage, float angle)
  73. {
  74. base.HurtHandler(target, damage, angle);
  75.  
  76. if (Hp <= 0) //死亡
  77. {
  78. StateController.Enable = false;
  79. MoveController.Enable = false;
  80. MoveController.ClearForce();
  81. Velocity = Vector2.Zero;
  82. AnimatedSprite.RotationDegrees = 0;
  83. StopCoroutine(_attaclCoroutine);
  84. }
  85. }
  86.  
  87. public override void Attack()
  88. {
  89. if (_attaclCoroutine < 0)
  90. {
  91. if (World.Current.Player != null) //玩家快没有子弹了, 就生成小兵
  92. {
  93. var total = 0;
  94. var itemSlot = World.Current.Player.WeaponPack.ItemSlot;
  95. for (var i = 0; i < itemSlot.Length; i++)
  96. {
  97. var item = itemSlot[i];
  98. if (item != null)
  99. {
  100. total += item.TotalAmmon;
  101. break;
  102. }
  103. }
  104.  
  105. if (total < 30)
  106. {
  107. var count = AffiliationArea.FindEnterItemsCount(o => o != this && o is AiRole aiRole && aiRole.IsEnemyWithPlayer());
  108. if (count == 0)
  109. {
  110. _attaclCoroutine = StartCoroutine(RunAttack4());
  111. return;
  112. }
  113. }
  114. }
  115. if (Hp / (float)MaxHp > 0.5f) //第一阶段
  116. {
  117. switch (Utils.Random.RandomRangeInt(0, 4))
  118. {
  119. case 0:
  120. _attaclCoroutine = StartCoroutine(RunAttack1());
  121. break;
  122. case 1:
  123. _attaclCoroutine = StartCoroutine(RunAttack3());
  124. break;
  125. case 2:
  126. _attaclCoroutine = StartCoroutine(RunAttack4());
  127. break;
  128. case 3:
  129. _attaclCoroutine = StartCoroutine(RunAttack5());
  130. break;
  131. case 4:
  132. _attaclCoroutine = StartCoroutine(RunAttack6());
  133. break;
  134. }
  135. }
  136. else //第二阶段
  137. {
  138. if (state == 0) //
  139. {
  140. state++;
  141. _attaclCoroutine = StartCoroutine(RunAttack2());
  142. }
  143. else if (state == 1)
  144. {
  145. state++;
  146. _attaclCoroutine = StartCoroutine(RunAttack7());
  147. }
  148. else
  149. {
  150. switch (Utils.Random.RandomRangeInt(0, 6))
  151. {
  152. case 0:
  153. _attaclCoroutine = StartCoroutine(RunAttack1());
  154. break;
  155. case 1:
  156. _attaclCoroutine = StartCoroutine(RunAttack2());
  157. break;
  158. case 2:
  159. _attaclCoroutine = StartCoroutine(RunAttack3());
  160. break;
  161. case 3:
  162. _attaclCoroutine = StartCoroutine(RunAttack4());
  163. break;
  164. case 4:
  165. _attaclCoroutine = StartCoroutine(RunAttack5());
  166. break;
  167. case 5:
  168. _attaclCoroutine = StartCoroutine(RunAttack6());
  169. break;
  170. case 6:
  171. _attaclCoroutine = StartCoroutine(RunAttack7());
  172. break;
  173. }
  174. }
  175. }
  176. }
  177. }
  178.  
  179. //发射两个子弹圈
  180. private IEnumerator RunAttack1()
  181. {
  182. var bulletData = FireManager.GetBulletData(this, 0, ExcelConfig.BulletBase_Map["0030"]);
  183. bulletData.Altitude = 1;
  184. AnimatedSprite.Play("readyAttack1");
  185. yield return ToSignal(AnimatedSprite, AnimatedSprite2D.SignalName.AnimationFinished);
  186. AnimatedSprite.Play("attack2");
  187. yield return new WaitForSeconds(0.4f);
  188. CreateBulletCircle(15, 0, bulletData, (shootBullet) =>
  189. {
  190. if (shootBullet is Bullet bullet)
  191. {
  192. var twistMovement = bullet.MoveController.AddForce(new TwistForce());
  193. twistMovement.MoveRotation = shootBullet.BulletData.Rotation;
  194. twistMovement.TimeOffset = Utils.Random.RandomRangeFloat(0, Mathf.Pi);
  195. }
  196. });
  197. yield return new WaitForSeconds(0.2f);
  198. CreateBulletCircle(60, 0, bulletData);
  199. yield return new WaitForSeconds(0.1f);
  200. CreateBulletCircle(60, 0, bulletData);
  201. yield return new WaitForSeconds(0.2f);
  202. CreateBulletCircle(15, Mathf.DegToRad(360 / 15f * 0.5f) , bulletData, (shootBullet) =>
  203. {
  204. if (shootBullet is Bullet bullet)
  205. {
  206. var twistMovement = bullet.MoveController.AddForce(new TwistForce());
  207. twistMovement.MoveRotation = shootBullet.BulletData.Rotation;
  208. twistMovement.TimeOffset = Utils.Random.RandomRangeFloat(0, Mathf.Pi);
  209. }
  210. });
  211. yield return new WaitForSeconds(0.5f);
  212.  
  213. AttackTimer = 1.5f;
  214. _attaclCoroutine = -1;
  215. }
  216.  
  217. //全屏发射子弹
  218. private IEnumerator RunAttack2()
  219. {
  220. var bulletData = FireManager.GetBulletData(this, 0, ExcelConfig.BulletBase_Map["0030"]);
  221. bulletData.Altitude = 1;
  222. AnimatedSprite.Play("readyAttack6");
  223. yield return ToSignal(AnimatedSprite, AnimatedSprite2D.SignalName.AnimationFinished);
  224. AnimatedSprite.Play("attack6");
  225. var count = 18;
  226. var angle = Mathf.DegToRad(360f / count * 0.5f);
  227. for (int i = 0; i < 15; i++)
  228. {
  229. if (i == 13)
  230. {
  231. CreateBulletCircle(60, 0, bulletData);
  232. }
  233. CreateBulletCircle(count, angle * i, bulletData);
  234. yield return new WaitForSeconds(0.4f);
  235. }
  236. AnimatedSprite.Play("endAttack6");
  237. yield return ToSignal(AnimatedSprite, AnimatedSprite2D.SignalName.AnimationFinished);
  238. AnimatedSprite.Play(AnimatorNames.Idle);
  239. AttackTimer = 2.5f;
  240. _attaclCoroutine = -1;
  241. }
  242.  
  243. //玩家方向发射扇形子弹
  244. private IEnumerator RunAttack3()
  245. {
  246. var count = 100;
  247. var r = Mathf.Pi;
  248. var d = r / count;
  249. AnimatedSprite.Play("readyAttack5");
  250. yield return ToSignal(AnimatedSprite, AnimatedSprite2D.SignalName.AnimationFinished);
  251. AnimatedSprite.Play("attack5");
  252. for (var j = 0; j < 3; j++)
  253. {
  254. var angle = Position.AngleToPoint(LookTarget.Position);
  255. var bulletData = FireManager.GetBulletData(this, angle - r * 0.5f, ExcelConfig.BulletBase_Map["0030"]);
  256. bulletData.Altitude = 1;
  257. for (var i = 0; i < 100; i++)
  258. {
  259. var clone = bulletData.Clone();
  260. clone.Position = FirePoint.GlobalPosition;
  261. clone.Rotation += i * d;
  262. clone.FlySpeed *= Utils.Random.RandomRangeFloat(1, 1.5f);
  263. var shootBullet = FireManager.ShootBullet(clone, Camp);
  264. if (shootBullet is Bullet bullet)
  265. {
  266. bullet.HideShadowSprite();
  267. var twistMovement = bullet.MoveController.AddForce(new TwistForce());
  268. twistMovement.MoveRotation = clone.Rotation;
  269. twistMovement.TimeOffset = Utils.Random.RandomRangeFloat(0, Mathf.Pi);
  270. }
  271.  
  272. if (i % 2 == 0)
  273. {
  274. yield return null;
  275. }
  276. }
  277. yield return new WaitForSeconds(1.5f);
  278. }
  279. AnimatedSprite.Play(AnimatorNames.Idle);
  280. AttackTimer = 2.5f;
  281. _attaclCoroutine = -1;
  282. }
  283.  
  284. //随机生成敌人
  285. private IEnumerator RunAttack4()
  286. {
  287. AnimatedSprite.Play("readyGenerate");
  288. yield return ToSignal(AnimatedSprite, AnimatedSprite2D.SignalName.AnimationFinished);
  289. AnimatedSprite.Play("generate");
  290. yield return new WaitForSeconds(0.3f);
  291. var count = (Hp / (float)MaxHp) < 0.5f ? Utils.Random.RandomRangeInt(2, 3) : 1;
  292. var positionArray = GetRandomPoint(count);
  293. for (var i = 0; i < count; i++)
  294. {
  295. var summons = Create<Summons>(Ids.Id_summons0001);
  296. summons.InitTarget(World.Player);
  297. summons.ThrowToPosition(Position, 40, 0, AffiliationArea.RoomInfo.ToGlobalPosition(positionArray[i]), 150);
  298. summons.PutDown(RoomLayerEnum.YSortLayer);
  299. yield return new WaitForSeconds(0.5f);
  300. }
  301. yield return new WaitForSeconds(1f);
  302.  
  303. AnimatedSprite.Play(AnimatorNames.Idle);
  304. AttackTimer = 2f;
  305. _attaclCoroutine = -1;
  306. }
  307.  
  308. //发射分裂子弹
  309. private IEnumerator RunAttack5()
  310. {
  311. AnimatedSprite.Play("readyAttack1");
  312. yield return ToSignal(AnimatedSprite, AnimatedSprite2D.SignalName.AnimationFinished);
  313. AnimatedSprite.Play("attack1");
  314. yield return new WaitForSeconds(0.2f);
  315.  
  316. for (int i = 0; i < 5; i++)
  317. {
  318. var bulletData = FireManager.GetBulletData(this, Utils.Random.RandomRangeFloat(0, Mathf.Pi * 2), ExcelConfig.BulletBase_Map["0034"]);
  319. bulletData.Altitude = 1;
  320. var shootBullet = FireManager.ShootBullet(bulletData, Camp);
  321. if (shootBullet is Bullet bullet)
  322. {
  323. bullet.HideShadowSprite();
  324. if (bullet is SplitBullet splitBullet)
  325. {
  326. var childBullet = FireManager.GetBulletData(this, 0, ExcelConfig.BulletBase_Map["0030"]);
  327. childBullet.Altitude = 1;
  328. splitBullet.SetSplitBullet(childBullet, 20);
  329. splitBullet.OnCreateSplitBulletEvent += iBullet =>
  330. {
  331. if (iBullet is Bullet bullet1)
  332. {
  333. bullet1.HideShadowSprite();
  334. }
  335. };
  336. }
  337. }
  338. yield return new WaitForSeconds(0.5f);
  339. }
  340. yield return new WaitForSeconds(1f);
  341. AnimatedSprite.Play(AnimatorNames.Idle);
  342. AttackTimer = 1.5f;
  343. _attaclCoroutine = -1;
  344. }
  345.  
  346. //发射一堆低速子弹
  347. private IEnumerator RunAttack6()
  348. {
  349. AnimatedSprite.Play("readyAttack1");
  350. yield return ToSignal(AnimatedSprite, AnimatedSprite2D.SignalName.AnimationFinished);
  351. AnimatedSprite.Play("attack1");
  352. yield return new WaitForSeconds(0.2f);
  353.  
  354. var bulletData = FireManager.GetBulletData(this, 0, ExcelConfig.BulletBase_Map["0030"]);
  355. bulletData.Altitude = 1;
  356. var count = 50;
  357. for (var i = 0; i < count; i++)
  358. {
  359. var clone = bulletData.Clone();
  360. clone.Position = Position;
  361. clone.Rotation = Utils.Random.RandomRangeFloat(0, Mathf.Pi * 2);
  362. clone.FlySpeed *= Utils.Random.RandomRangeFloat(0.2f, 0.9f);
  363. var shootBullet = FireManager.ShootBullet(clone, Camp);
  364. if (shootBullet is Bullet bullet)
  365. {
  366. bullet.HideShadowSprite();
  367. }
  368. if (count % 5 == 0)
  369. {
  370. yield return null;
  371. }
  372. }
  373. yield return new WaitForSeconds(1f);
  374. AnimatedSprite.Play(AnimatorNames.Idle);
  375.  
  376. AttackTimer = 1f;
  377. _attaclCoroutine = -1;
  378. }
  379.  
  380. //向上发射火箭炮(非常难躲避)
  381. private IEnumerator RunAttack7()
  382. {
  383. AnimatedSprite.Play("readyAttack4");
  384. yield return ToSignal(AnimatedSprite, AnimatedSprite2D.SignalName.AnimationFinished);
  385.  
  386. var count = 3;
  387. _randomPosList = GetRandomPoint(count * 4).ToList();
  388. for (int i = 0; i < count; i++)
  389. {
  390. AnimationPlayer.Play("attack4");
  391. yield return ToSignal(AnimationPlayer, AnimationMixer.SignalName.AnimationFinished);
  392. }
  393. AnimatedSprite.Play(AnimatorNames.Idle);
  394.  
  395. AttackTimer = 6f;
  396. _attaclCoroutine = -1;
  397. }
  398.  
  399. private List<Vector2> _randomPosList;
  400. private void CreateMissileBullet(NodePath node)
  401. {
  402. if (_randomPosList == null || _randomPosList.Count == 0)
  403. {
  404. return;
  405. }
  406. var node2D = GetNode<Node2D>(node);
  407. var bullet = ObjectManager.GetActivityObject<SpecialBullet0001>(Ids.Id_special0001);
  408. bullet.InitBullet("0030", 10, this, AffiliationArea.RoomInfo.ToGlobalPosition(_randomPosList[_randomPosList.Count - 1]));
  409. _randomPosList.RemoveAt(_randomPosList.Count - 1);
  410. var localPos = node2D.Position;
  411. bullet.Position = Position + new Vector2(localPos.X, 0);
  412. bullet.Altitude = -localPos.Y;
  413. bullet.VerticalSpeed = 800;
  414. bullet.OnCreateSplitBulletEvent += b =>
  415. {
  416. if (b is Bullet blt)
  417. {
  418. blt.Altitude = 1;
  419. blt.HideShadowSprite();
  420. }
  421. };
  422. bullet.PutDown(RoomLayerEnum.YSortLayer, false);
  423. bullet.UpdateFall((float)GetProcessDeltaTime());
  424. bullet.HideShadowSprite();
  425. }
  426.  
  427. private Vector2[] GetRandomPoint(int count)
  428. {
  429. var tileInfo = AffiliationArea.RoomInfo.RoomSplit.TileInfo;
  430. if (_vertices == null)
  431. {
  432. var serializeVector2s = tileInfo.NavigationVertices;
  433. _vertices = new List<Vector2>();
  434. foreach (var sv2 in serializeVector2s)
  435. {
  436. _vertices.Add(sv2.AsVector2());
  437. }
  438. }
  439.  
  440. var positionArray = World.Random.GetRandomPositionInPolygon(_vertices, tileInfo.NavigationPolygon, count);
  441. return positionArray;
  442. }
  443.  
  444. private void CreateBulletCircle(int count, float offsetAngle, BulletData bulletData, Action<IBullet> callback = null)
  445. {
  446. var pos = FirePoint.GlobalPosition;
  447. for (var i = 0; i < count; i++)
  448. {
  449. var clone = bulletData.Clone();
  450. clone.Position = pos;
  451. clone.Rotation = Mathf.Pi * 2 / count * i + offsetAngle;
  452. var shootBullet = FireManager.ShootBullet(clone, Camp);
  453. if (shootBullet is Bullet bullet)
  454. {
  455. bullet.HideShadowSprite();
  456. }
  457.  
  458. if (callback != null)
  459. {
  460. callback(shootBullet);
  461. }
  462. }
  463. }
  464. }