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