SkillSelectionController.ts 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. import { _decorator, Component, Node, Button, find, Label, Sprite, Vec3, CCFloat } from 'cc';
  2. import { GameManager } from '../../LevelSystem/GameManager';
  3. import { SkillButtonAnimator } from './SkillButtonAnimator';
  4. import { GamePause } from '../GamePause';
  5. const { ccclass, property } = _decorator;
  6. /**
  7. * SkillSelectionController
  8. * 放在 Canvas/SelectSkillUI 节点上。
  9. * 负责监听技能按钮点击,并按顺序播放缩小动画,最后关闭整个 SelectSkillUI。
  10. */
  11. @ccclass('SkillSelectionController')
  12. export class SkillSelectionController extends Component {
  13. @property({ type: [Node], tooltip: '技能按钮节点列表,留空则自动从 SkillsContainer 获取' })
  14. public skillButtons: Node[] = [];
  15. @property({ type: CCFloat, tooltip: '收缩动画时长' })
  16. public shrinkDuration: number = 0.3;
  17. // 防止重复点击标记
  18. private _clicked = false;
  19. start() {
  20. this.setupSkillButtons();
  21. }
  22. private setupSkillButtons() {
  23. if (this.skillButtons.length === 0) {
  24. const container = this.node.getChildByName('SkillsContainer');
  25. if (container) {
  26. this.skillButtons = container.children.slice();
  27. }
  28. }
  29. this.skillButtons.forEach(btnNode => {
  30. const btn = btnNode.getComponent(Button);
  31. if (btn) {
  32. btn.node.on(Button.EventType.CLICK, () => this.onSkillSelected(btnNode), this);
  33. }
  34. });
  35. }
  36. /**
  37. * 玩家选择某技能按钮
  38. */
  39. private onSkillSelected(selectedBtn: Node) {
  40. if (this._clicked) return; // 只允许一次
  41. this._clicked = true;
  42. // 禁用所有按钮交互
  43. this.skillButtons.forEach(btn => {
  44. const b = btn.getComponent(Button);
  45. if (b) b.interactable = false;
  46. });
  47. const otherBtns = this.skillButtons.filter(btn => btn !== selectedBtn);
  48. let finishedOthers = 0;
  49. // 所有其他按钮完成动画后,再收缩选中按钮
  50. const onOtherFinished = () => {
  51. finishedOthers++;
  52. if (finishedOthers >= otherBtns.length) {
  53. // 收缩选中按钮
  54. const selAnim = selectedBtn.getComponent(SkillButtonAnimator);
  55. selAnim?.playShrink(this.shrinkDuration, undefined, () => {
  56. // 关闭整个 UI
  57. this.node.active = false;
  58. // 恢复游戏并重置能量 - 使用GamePause
  59. const gamePause = GamePause.getInstance();
  60. if (gamePause) {
  61. gamePause.resumeGame();
  62. }
  63. const gm = this.getGameManager();
  64. if (gm) {
  65. gm.resetEnergy();
  66. }
  67. // 关闭后立刻重置UI
  68. this.resetUI();
  69. });
  70. }
  71. };
  72. // 播放其他按钮动画
  73. const targetPos = selectedBtn.position.clone();
  74. otherBtns.forEach(btn => {
  75. const anim = btn.getComponent(SkillButtonAnimator);
  76. anim?.playShrink(this.shrinkDuration, targetPos, onOtherFinished);
  77. });
  78. }
  79. /**
  80. * 重置 UI 状态,供下次开启时使用
  81. */
  82. private resetUI() {
  83. this._clicked = false;
  84. // 重新启用所有按钮交互
  85. this.skillButtons.forEach(btn => {
  86. const b = btn.getComponent(Button);
  87. if (b) b.interactable = true;
  88. // 重置按钮动画状态
  89. const anim = btn.getComponent(SkillButtonAnimator);
  90. anim?.resetState();
  91. });
  92. }
  93. private getGameManager(): GameManager | null {
  94. const gmNode = find('Canvas/GameLevelUI/GameManager');
  95. return gmNode?.getComponent(GameManager) || null;
  96. }
  97. }