Newer
Older
DungeonShooting / DungeonShooting_Godot / src / game / item / weapon / Weapon.cs
@小李xl 小李xl on 4 Nov 2022 23 KB 小修改
  1. using Godot;
  2. using System;
  3.  
  4. /// <summary>
  5. /// 武器的基类
  6. /// </summary>
  7. public abstract class Weapon : ActivityObject
  8. {
  9. /// <summary>
  10. /// 武器的唯一id
  11. /// </summary>
  12. public string Id { get; }
  13.  
  14. /// <summary>
  15. /// 开火回调事件
  16. /// </summary>
  17. public event Action<Weapon> FireEvent;
  18.  
  19. /// <summary>
  20. /// 属性数据
  21. /// </summary>
  22. public WeaponAttribute Attribute { get; private set; }
  23. /// <summary>
  24. /// 动画播放器
  25. /// </summary>
  26. /// <value></value>
  27. public AnimationPlayer AnimationPlayer { get; private set; }
  28.  
  29. /// <summary>
  30. /// 武器攻击的目标阵营
  31. /// </summary>
  32. public CampEnum TargetCamp { get; set; }
  33.  
  34. /// <summary>
  35. /// 该武器的拥有者
  36. /// </summary>
  37. public Role Master { get; private set; }
  38.  
  39. /// <summary>
  40. /// 当前弹夹弹药剩余量
  41. /// </summary>
  42. public int CurrAmmo { get; private set; }
  43. /// <summary>
  44. /// 剩余弹药量
  45. /// </summary>
  46. public int ResidueAmmo { get; private set; }
  47.  
  48. /// <summary>
  49. /// 武器管的开火点
  50. /// </summary>
  51. public Position2D FirePoint { get; private set; }
  52. /// <summary>
  53. /// 武器管的原点
  54. /// </summary>
  55. public Position2D OriginPoint { get; private set; }
  56. /// <summary>
  57. /// 弹壳抛出的点
  58. /// </summary>
  59. public Position2D ShellPoint { get; private set; }
  60. /// <summary>
  61. /// 碰撞器节点
  62. /// </summary>
  63. /// <value></value>
  64. public CollisionShape2D CollisionShape2D { get; private set; }
  65. /// <summary>
  66. /// 武器的当前散射半径
  67. /// </summary>
  68. public float CurrScatteringRange { get; private set; } = 0;
  69. /// <summary>
  70. /// 是否在换弹中
  71. /// </summary>
  72. /// <value></value>
  73. public bool Reloading { get; private set; } = false;
  74. /// <summary>
  75. /// 换弹计时器
  76. /// </summary>
  77. public float ReloadTimer { get; private set; } = 0;
  78. /// <summary>
  79. /// 换弹进度 (0 - 1)
  80. /// </summary>
  81. public float ReloadProgress
  82. {
  83. get
  84. {
  85. if (Attribute.AloneReload)
  86. {
  87. var num = 1f / Attribute.AmmoCapacity;
  88. return num * (Attribute.AmmoCapacity - CurrAmmo - 1) + num * (ReloadTimer / Attribute.ReloadTime);
  89. }
  90. return ReloadTimer / Attribute.ReloadTime;
  91. }
  92. }
  93.  
  94. //是否按下
  95. private bool triggerFlag = false;
  96. //扳机计时器
  97. private float triggerTimer = 0;
  98. //开火前延时时间
  99. private float delayedTime = 0;
  100. //开火间隙时间
  101. private float fireInterval = 0;
  102. //开火武器口角度
  103. private float fireAngle = 0;
  104. //攻击冷却计时
  105. private float attackTimer = 0;
  106. //攻击状态
  107. private bool attackFlag = false;
  108. //按下的时间
  109. private float downTimer = 0;
  110. //松开的时间
  111. private float upTimer = 0;
  112. //连发次数
  113. private float continuousCount = 0;
  114. //连发状态记录
  115. private bool continuousShootFlag = false;
  116.  
  117. /// <summary>
  118. /// 根据属性创建一把武器
  119. /// </summary>
  120. /// <param name="id">武器唯一id</param>
  121. /// <param name="attribute">属性</param>
  122. public Weapon(string id, WeaponAttribute attribute): base(attribute.WeaponPrefab)
  123. {
  124. Id = id;
  125. Attribute = attribute;
  126.  
  127. FirePoint = GetNode<Position2D>("WeaponBody/FirePoint");
  128. OriginPoint = GetNode<Position2D>("WeaponBody/OriginPoint");
  129. ShellPoint = GetNode<Position2D>("WeaponBody/ShellPoint");
  130. AnimationPlayer = GetNode<AnimationPlayer>("WeaponBody/AnimationPlayer");
  131. CollisionShape2D = GetNode<CollisionShape2D>("WeaponBody/Collision");
  132.  
  133. //更新图片
  134. var texture = ResourceLoader.Load<Texture>(Attribute.Sprite);
  135. SetDefaultTexture(texture);
  136. AnimatedSprite.Position = Attribute.CenterPosition;
  137.  
  138. //开火位置
  139. FirePoint.Position = new Vector2(Attribute.FirePosition.x, -Attribute.FirePosition.y);
  140. OriginPoint.Position = new Vector2(0, -Attribute.FirePosition.y);
  141.  
  142. //弹药量
  143. CurrAmmo = Attribute.AmmoCapacity;
  144. //剩余弹药量
  145. ResidueAmmo = Attribute.MaxAmmoCapacity - Attribute.AmmoCapacity;
  146. }
  147.  
  148. /// <summary>
  149. /// 当按下扳机时调用
  150. /// </summary>
  151. protected abstract void OnDownTrigger();
  152.  
  153. /// <summary>
  154. /// 当松开扳机时调用
  155. /// </summary>
  156. protected abstract void OnUpTrigger();
  157.  
  158. /// <summary>
  159. /// 单次开火时调用的函数
  160. /// </summary>
  161. protected abstract void OnFire();
  162.  
  163. /// <summary>
  164. /// 发射子弹时调用的函数, 每发射一枚子弹调用一次,
  165. /// 如果做霰弹武器效果, 一次开火发射5枚子弹, 则该函数调用5次
  166. /// </summary>
  167. protected abstract void OnShoot();
  168.  
  169. /// <summary>
  170. /// 当开始换弹时调用
  171. /// </summary>
  172. protected abstract void OnReload();
  173.  
  174. /// <summary>
  175. /// 当换弹完成时调用
  176. /// </summary>
  177. protected abstract void OnReloadFinish();
  178.  
  179. /// <summary>
  180. /// 当武器被拾起时调用
  181. /// </summary>
  182. /// <param name="master">拾起该武器的角色</param>
  183. protected abstract void OnPickUp(Role master);
  184.  
  185. /// <summary>
  186. /// 当武器从武器袋中移除时调用
  187. /// </summary>
  188. protected abstract void OnRemove();
  189.  
  190. /// <summary>
  191. /// 当武器被激活时调用, 也就是使用当武器是调用
  192. /// </summary>
  193. protected abstract void OnActive();
  194.  
  195. /// <summary>
  196. /// 当武器被收起时调用
  197. /// </summary>
  198. protected abstract void OnConceal();
  199.  
  200. public override void _Process(float delta)
  201. {
  202. base._Process(delta);
  203. if (Master == null) //这把武器被扔在地上
  204. {
  205. Reloading = false;
  206. ReloadTimer = 0;
  207. triggerTimer = triggerTimer > 0 ? triggerTimer - delta : 0;
  208. triggerFlag = false;
  209. attackFlag = false;
  210. attackTimer = attackTimer > 0 ? attackTimer - delta : 0;
  211. CurrScatteringRange = Mathf.Max(CurrScatteringRange - Attribute.ScatteringRangeBackSpeed * delta, Attribute.StartScatteringRange);
  212. continuousCount = 0;
  213. delayedTime = 0;
  214. }
  215. else if (Master.Holster.ActiveWeapon != this) //当前武器没有被使用
  216. {
  217. Reloading = false;
  218. ReloadTimer = 0;
  219. triggerTimer = triggerTimer > 0 ? triggerTimer - delta : 0;
  220. triggerFlag = false;
  221. attackFlag = false;
  222. attackTimer = attackTimer > 0 ? attackTimer - delta : 0;
  223. CurrScatteringRange = Mathf.Max(CurrScatteringRange - Attribute.ScatteringRangeBackSpeed * delta, Attribute.StartScatteringRange);
  224. continuousCount = 0;
  225. delayedTime = 0;
  226. }
  227. else //正在使用中
  228. {
  229.  
  230. //换弹
  231. if (Reloading)
  232. {
  233. ReloadTimer -= delta;
  234. if (ReloadTimer <= 0)
  235. {
  236. ReloadSuccess();
  237. }
  238. }
  239.  
  240. if (triggerFlag)
  241. {
  242. if (upTimer > 0) //第一帧按下扳机
  243. {
  244. upTimer = 0;
  245. DownTrigger();
  246. }
  247. downTimer += delta;
  248. }
  249. else
  250. {
  251. if (downTimer > 0) //第一帧松开扳机
  252. {
  253. downTimer = 0;
  254. UpTrigger();
  255. }
  256. upTimer += delta;
  257. }
  258.  
  259. // 攻击的计时器
  260. if (attackTimer > 0)
  261. {
  262. attackTimer -= delta;
  263. if (attackTimer < 0)
  264. {
  265. delayedTime += attackTimer;
  266. attackTimer = 0;
  267. }
  268. }
  269. else if (delayedTime > 0) //攻击延时
  270. {
  271. delayedTime -= delta;
  272. if (attackTimer < 0)
  273. {
  274. delayedTime = 0;
  275. }
  276. }
  277.  
  278. //连发判断
  279. if (continuousCount > 0 && delayedTime <= 0 && attackTimer <= 0)
  280. {
  281. //开火
  282. TriggerFire();
  283. }
  284.  
  285. if (!attackFlag && attackTimer <= 0)
  286. {
  287. CurrScatteringRange = Mathf.Max(CurrScatteringRange - Attribute.ScatteringRangeBackSpeed * delta, Attribute.StartScatteringRange);
  288. }
  289. triggerTimer = triggerTimer > 0 ? triggerTimer - delta : 0;
  290. triggerFlag = false;
  291. attackFlag = false;
  292.  
  293. //武器身回归
  294. Position = Position.MoveToward(Vector2.Zero, 35 * delta);
  295. if (fireInterval == 0)
  296. {
  297. RotationDegrees = 0;
  298. }
  299. else
  300. {
  301. RotationDegrees = Mathf.Lerp(0, fireAngle, attackTimer / fireInterval);
  302. }
  303. }
  304. }
  305.  
  306. /// <summary>
  307. /// 扳机函数, 调用即视为扣动扳机
  308. /// </summary>
  309. public void Trigger()
  310. {
  311. //是否第一帧按下
  312. var justDown = downTimer == 0;
  313. //是否能发射
  314. var flag = false;
  315. if (continuousCount <= 0) //不能处于连发状态下
  316. {
  317. if (Attribute.ContinuousShoot) //自动射击
  318. {
  319. if (triggerTimer > 0)
  320. {
  321. if (continuousShootFlag)
  322. {
  323. flag = true;
  324. }
  325. }
  326. else
  327. {
  328. flag = true;
  329. if (delayedTime <= 0 && attackTimer <= 0)
  330. {
  331. continuousShootFlag = true;
  332. }
  333. }
  334. }
  335. else //半自动
  336. {
  337. if (justDown && triggerTimer <= 0)
  338. {
  339. flag = true;
  340. }
  341. }
  342. }
  343.  
  344. if (flag)
  345. {
  346. var fireFlag = true; //是否能开火
  347. if (Reloading) //换弹中
  348. {
  349. if (CurrAmmo > 0 && Attribute.AloneReload && Attribute.AloneReloadCanShoot) //立即停止换弹
  350. {
  351. Reloading = false;
  352. ReloadTimer = 0;
  353. }
  354. else
  355. {
  356. fireFlag = false;
  357. }
  358. }
  359. else if (CurrAmmo <= 0)
  360. {
  361. fireFlag = false;
  362. //子弹不够
  363. _Reload();
  364. }
  365.  
  366. if (fireFlag)
  367. {
  368. if (justDown)
  369. {
  370. //开火前延时
  371. delayedTime = Attribute.DelayedTime;
  372. //扳机按下间隔
  373. triggerTimer = Attribute.TriggerInterval;
  374. //连发数量
  375. if (!Attribute.ContinuousShoot)
  376. {
  377. continuousCount = MathUtils.RandRangeInt(Attribute.MinContinuousCount, Attribute.MaxContinuousCount);
  378. }
  379. }
  380. if (delayedTime <= 0 && attackTimer <= 0)
  381. {
  382. TriggerFire();
  383. }
  384. attackFlag = true;
  385. }
  386.  
  387. }
  388. triggerFlag = true;
  389. }
  390.  
  391. /// <summary>
  392. /// 刚按下扳机
  393. /// </summary>
  394. private void DownTrigger()
  395. {
  396. OnDownTrigger();
  397. }
  398.  
  399. /// <summary>
  400. /// 刚松开扳机
  401. /// </summary>
  402. private void UpTrigger()
  403. {
  404. continuousShootFlag = false;
  405. if (delayedTime > 0)
  406. {
  407. continuousCount = 0;
  408. }
  409. OnUpTrigger();
  410. }
  411.  
  412. /// <summary>
  413. /// 触发开火
  414. /// </summary>
  415. private void TriggerFire()
  416. {
  417. continuousCount = continuousCount > 0 ? continuousCount - 1 : 0;
  418.  
  419. //减子弹数量
  420. CurrAmmo--;
  421. //开火间隙
  422. fireInterval = 60 / Attribute.StartFiringSpeed;
  423. //攻击冷却
  424. attackTimer += fireInterval;
  425.  
  426. //触发开火函数
  427. OnFire();
  428.  
  429. //开火发射的子弹数量
  430. var bulletCount = MathUtils.RandRangeInt(Attribute.MaxFireBulletCount, Attribute.MinFireBulletCount);
  431. //武器口角度
  432. var angle = new Vector2(GameConfig.ScatteringDistance, CurrScatteringRange).Angle();
  433.  
  434. //先算武器口方向
  435. var tempAngle = Mathf.Rad2Deg((float)GD.RandRange(-angle, angle));
  436. //创建子弹
  437. for (int i = 0; i < bulletCount; i++)
  438. {
  439. //发射子弹
  440. OnShoot();
  441. }
  442.  
  443. //当前的散射半径
  444. CurrScatteringRange = Mathf.Min(CurrScatteringRange + Attribute.ScatteringRangeAddValue, Attribute.FinalScatteringRange);
  445. //武器的旋转角度
  446. tempAngle -= Attribute.UpliftAngle;
  447. RotationDegrees = tempAngle;
  448. fireAngle = tempAngle;
  449. //武器身位置
  450. Position = new Vector2(Mathf.Max(-Attribute.MaxBacklash, Position.x - MathUtils.RandRange(Attribute.MinBacklash, Attribute.MaxBacklash)), Position.y);
  451.  
  452. if (FireEvent != null)
  453. {
  454. FireEvent(this);
  455. }
  456. }
  457.  
  458. /// <summary>
  459. /// 返回弹药是否到达上限
  460. /// </summary>
  461. public bool IsFullAmmo()
  462. {
  463. return CurrAmmo + ResidueAmmo >= Attribute.MaxAmmoCapacity;
  464. }
  465.  
  466. /// <summary>
  467. /// 返回是否弹药耗尽
  468. /// </summary>
  469. public bool IsEmptyAmmo()
  470. {
  471. return CurrAmmo + ResidueAmmo == 0;
  472. }
  473.  
  474. /// <summary>
  475. /// 拾起的弹药数量, 如果到达容量上限, 则返回拾取完毕后剩余的弹药数量
  476. /// </summary>
  477. /// <param name="count">弹药数量</param>
  478. private int PickUpAmmo(int count)
  479. {
  480. var num = ResidueAmmo;
  481. ResidueAmmo = Mathf.Min(ResidueAmmo + count, Attribute.MaxAmmoCapacity - CurrAmmo);
  482. return count - ResidueAmmo + num;
  483. }
  484.  
  485. /// <summary>
  486. /// 触发换弹
  487. /// </summary>
  488. public void _Reload()
  489. {
  490. if (CurrAmmo < Attribute.AmmoCapacity && ResidueAmmo > 0 && !Reloading)
  491. {
  492. Reloading = true;
  493. ReloadTimer = Attribute.ReloadTime;
  494. OnReload();
  495. }
  496. }
  497.  
  498. /// <summary>
  499. /// 换弹计时器时间到, 执行换弹操作
  500. /// </summary>
  501. private void ReloadSuccess()
  502. {
  503. if (Attribute.AloneReload) //单独装填
  504. {
  505. if (ResidueAmmo >= Attribute.AloneReloadCount) //剩余子弹充足
  506. {
  507. if (CurrAmmo + Attribute.AloneReloadCount <= Attribute.AmmoCapacity)
  508. {
  509. ResidueAmmo -= Attribute.AloneReloadCount;
  510. CurrAmmo += Attribute.AloneReloadCount;
  511. }
  512. else //子弹满了
  513. {
  514. var num = Attribute.AmmoCapacity - CurrAmmo;
  515. CurrAmmo = Attribute.AmmoCapacity;
  516. ResidueAmmo -= num;
  517. }
  518. }
  519. else if (ResidueAmmo != 0) //剩余子弹不足
  520. {
  521. if (ResidueAmmo + CurrAmmo <= Attribute.AmmoCapacity)
  522. {
  523. CurrAmmo += ResidueAmmo;
  524. ResidueAmmo = 0;
  525. }
  526. else //子弹满了
  527. {
  528. var num = Attribute.AmmoCapacity - CurrAmmo;
  529. CurrAmmo = Attribute.AmmoCapacity;
  530. ResidueAmmo -= num;
  531. }
  532. }
  533. if (ResidueAmmo == 0 || CurrAmmo == Attribute.AmmoCapacity) //换弹结束
  534. {
  535. Reloading = false;
  536. ReloadTimer = 0;
  537. OnReloadFinish();
  538. }
  539. else
  540. {
  541. ReloadTimer = Attribute.ReloadTime;
  542. OnReload();
  543. }
  544. }
  545. else //换弹结束
  546. {
  547. if (ResidueAmmo >= Attribute.AmmoCapacity)
  548. {
  549. ResidueAmmo -= Attribute.AmmoCapacity - CurrAmmo;
  550. CurrAmmo = Attribute.AmmoCapacity;
  551. }
  552. else
  553. {
  554. CurrAmmo = ResidueAmmo;
  555. ResidueAmmo = 0;
  556. }
  557. Reloading = false;
  558. ReloadTimer = 0;
  559. OnReloadFinish();
  560. }
  561. }
  562.  
  563. public override CheckInteractiveResult CheckInteractive(ActivityObject master)
  564. {
  565. var result = new CheckInteractiveResult(this);
  566. if (master is Role roleMaster) //碰到角色
  567. {
  568. if (Master == null)
  569. {
  570. var masterWeapon = roleMaster.Holster.ActiveWeapon;
  571. //查找是否有同类型武器
  572. var index = roleMaster.Holster.FindWeapon(Id);
  573. if (index != -1) //如果有这个武器
  574. {
  575. if (CurrAmmo + ResidueAmmo != 0) //子弹不为空
  576. {
  577. var targetWeapon = roleMaster.Holster.GetWeapon(index);
  578. if (!targetWeapon.IsFullAmmo()) //背包里面的武器子弹未满
  579. {
  580. //可以互动拾起弹药
  581. result.CanInteractive = true;
  582. result.Message = Attribute.Name;
  583. result.ShowIcon = "res://resource/sprite/ui/icon/icon_bullet.png";
  584. return result;
  585. }
  586. }
  587. }
  588. else //没有武器
  589. {
  590. if (roleMaster.Holster.CanPickupWeapon(this)) //能拾起武器
  591. {
  592. //可以互动, 拾起武器
  593. result.CanInteractive = true;
  594. result.Message = Attribute.Name;
  595. result.ShowIcon = "res://resource/sprite/ui/icon/icon_pickup.png";
  596. return result;
  597. }
  598. else if (masterWeapon != null && masterWeapon.Attribute.WeightType == Attribute.WeightType) //替换武器
  599. {
  600. //可以互动, 切换武器
  601. result.CanInteractive = true;
  602. result.Message = Attribute.Name;
  603. result.ShowIcon = "res://resource/sprite/ui/icon/icon_replace.png";
  604. return result;
  605. }
  606. }
  607. }
  608. }
  609. return result;
  610. }
  611.  
  612. public override void Interactive(ActivityObject master)
  613. {
  614. if (master is Role roleMaster) //与role碰撞
  615. {
  616. var holster = roleMaster.Holster;
  617. //查找是否有同类型武器
  618. var index = holster.FindWeapon(Id);
  619. if (index != -1) //如果有这个武器
  620. {
  621. if (CurrAmmo + ResidueAmmo == 0) //没有子弹了
  622. {
  623. return;
  624. }
  625.  
  626. var weapon = holster.GetWeapon(index);
  627. //子弹上限
  628. var maxCount = Attribute.MaxAmmoCapacity;
  629. //是否捡到子弹
  630. var flag = false;
  631. if (ResidueAmmo > 0 && weapon.CurrAmmo + weapon.ResidueAmmo < maxCount)
  632. {
  633. var count = weapon.PickUpAmmo(ResidueAmmo);
  634. if (count != ResidueAmmo)
  635. {
  636. ResidueAmmo = count;
  637. flag = true;
  638. }
  639. }
  640.  
  641. if (CurrAmmo > 0 && weapon.CurrAmmo + weapon.ResidueAmmo < maxCount)
  642. {
  643. var count = weapon.PickUpAmmo(CurrAmmo);
  644. if (count != CurrAmmo)
  645. {
  646. CurrAmmo = count;
  647. flag = true;
  648. }
  649. }
  650.  
  651. //播放互动效果
  652. if (flag)
  653. {
  654. Throw(new Vector2(30, 15), GlobalPosition, 0, 0,
  655. MathUtils.RandRangeInt(-20, 20), MathUtils.RandRangeInt(20, 50),
  656. MathUtils.RandRangeInt(-180, 180));
  657. }
  658. }
  659. else //没有武器
  660. {
  661. if (holster.PickupWeapon(this) == -1)
  662. {
  663. var slot = holster.SlotList[holster.ActiveIndex];
  664. if (slot.Type == Attribute.WeightType)
  665. {
  666. var weapon = holster.RemoveWeapon(holster.ActiveIndex);
  667. weapon.TriggerThrowWeapon(roleMaster);
  668. roleMaster.PickUpWeapon(this);
  669. }
  670. }
  671. }
  672. }
  673. }
  674.  
  675. /// <summary>
  676. /// 触发扔掉武器操作
  677. /// </summary>
  678. /// <param name="master">触发扔掉该武器的的角色</param>
  679. public void TriggerThrowWeapon(Role master)
  680. {
  681. //阴影偏移
  682. ShadowOffset = new Vector2(0, 2);
  683. if (master.Face == FaceDirection.Left)
  684. {
  685. Scale *= new Vector2(1, -1);
  686. RotationDegrees = 180;
  687. }
  688. var startHeight = 6;
  689. var direction = master.GlobalRotationDegrees + MathUtils.RandRangeInt(-20, 20);
  690. var xf = 30;
  691. var yf = MathUtils.RandRangeInt(60, 120);
  692. var rotate = MathUtils.RandRangeInt(-180, 180);
  693. Throw(new Vector2(30, 15), master.MountPoint.GlobalPosition, startHeight, direction, xf, yf, rotate, true);
  694. }
  695. public override void OnThrowOver()
  696. {
  697. //启用碰撞
  698. CollisionShape2D.Disabled = false;
  699. }
  700.  
  701. /// <summary>
  702. /// 触发拾起
  703. /// </summary>
  704. public void _PickUpWeapon(Role master)
  705. {
  706. Master = master;
  707. //握把位置
  708. AnimatedSprite.Position = Attribute.HoldPosition;
  709. //停止动画
  710. AnimationPlayer.Stop();
  711. //清除泛白效果
  712. ShaderMaterial sm = (ShaderMaterial) AnimatedSprite.Material;
  713. sm.SetShaderParam("schedule", 0);
  714. ZIndex = 0;
  715. //禁用碰撞
  716. CollisionShape2D.Disabled = true;
  717. OnPickUp(master);
  718. }
  719.  
  720. /// <summary>
  721. /// 触发移除
  722. /// </summary>a
  723. public void _Remove()
  724. {
  725. Master = null;
  726. AnimatedSprite.Position = Attribute.CenterPosition;
  727. AnimationPlayer.Play("Floodlight");
  728. OnRemove();
  729. }
  730.  
  731. /// <summary>
  732. /// 触发启用武器
  733. /// </summary>
  734. public void _Active()
  735. {
  736. ShadowOffset = new Vector2(0, Master.GlobalPosition.y - GlobalPosition.y);
  737. ShowShadowSprite();
  738. OnActive();
  739. }
  740.  
  741. /// <summary>
  742. /// 触发收起武器
  743. /// </summary>
  744. public void _Conceal()
  745. {
  746. HideShadowSprite();
  747. OnConceal();
  748. }
  749.  
  750. /// <summary>
  751. /// 实例化并返回子弹对象
  752. /// </summary>
  753. /// <param name="bulletPack">子弹的预制体</param>
  754. protected T CreateBullet<T>(PackedScene bulletPack, Vector2 globalPostion, float globalRotation, Node parent = null) where T : Node2D, IBullet
  755. {
  756. return (T)CreateBullet(bulletPack, globalPostion, globalRotation, parent);
  757. }
  758.  
  759. /// <summary>
  760. /// 实例化并返回子弹对象
  761. /// </summary>
  762. /// <param name="bulletPack">子弹的预制体</param>
  763. protected IBullet CreateBullet(PackedScene bulletPack, Vector2 globalPostion, float globalRotation, Node parent = null)
  764. {
  765. // 实例化子弹
  766. Node2D bullet = bulletPack.Instance<Node2D>();
  767. // 设置坐标
  768. bullet.GlobalPosition = globalPostion;
  769. // 旋转角度
  770. bullet.GlobalRotation = globalRotation;
  771. if (parent == null)
  772. {
  773. GameApplication.Instance.Room.SortRoot.AddChild(bullet);
  774. }
  775. else
  776. {
  777. parent.AddChild(bullet);
  778. }
  779. // 调用初始化
  780. IBullet result = (IBullet)bullet;
  781. result.Init(TargetCamp, this, null);
  782. return result;
  783. }
  784. }