UIStateManager.ts 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. import { _decorator, Component, Node, Button, find, Label } from 'cc';
  2. import { BaseSingleton } from '../Core/BaseSingleton';
  3. import EventBus, { GameEvents } from '../Core/EventBus';
  4. const { ccclass, property } = _decorator;
  5. /**
  6. * UIStateManager
  7. * 负责游戏内 UI 面板的显示/隐藏,以及按钮事件分发。
  8. * 注意:仅处理 Canvas/GameLevelUI 下与战斗胜败相关的 UI。
  9. */
  10. @ccclass('UIStateManager')
  11. export class UIStateManager extends BaseSingleton {
  12. public static _instance: UIStateManager;
  13. @property({ type: Node, tooltip: '游戏结束面板 (Canvas/GameEnd)' })
  14. public endPanel: Node = null;
  15. // 控制是否响应游戏结束事件的标志
  16. private shouldRespondToGameEvents: boolean = true;
  17. protected init() {
  18. // 自动查找面板
  19. if (!this.endPanel) {
  20. this.endPanel = find('Canvas/GameEnd');
  21. }
  22. // 默认隐藏
  23. if (this.endPanel) this.endPanel.active = false;
  24. // 绑定按钮
  25. this.bindPanelButtons();
  26. // 监听事件
  27. EventBus.getInstance().on(GameEvents.GAME_SUCCESS, this.onGameSuccess, this);
  28. EventBus.getInstance().on(GameEvents.GAME_DEFEAT, this.onGameDefeat, this);
  29. EventBus.getInstance().on(GameEvents.RESET_UI_STATES, this.closeAllPanels, this);
  30. }
  31. private bindPanelButtons() {
  32. this.bindButtonsInPanel(this.endPanel);
  33. }
  34. private bindButtonsInPanel(panel: Node) {
  35. if (!panel) return;
  36. const buttons = panel.getComponentsInChildren(Button);
  37. buttons.forEach(btn => {
  38. btn.node.on(Button.EventType.CLICK, () => {
  39. EventBus.getInstance().emit(btn.node.name.toUpperCase() + '_CLICK');
  40. });
  41. });
  42. }
  43. /**
  44. * 设置游戏结束UI的EndLabel文本
  45. * @param text 要显示的文本 ('SUCCESS' 或 'DEFEAT')
  46. */
  47. private setEndLabelText(text: string) {
  48. if (!this.endPanel) return;
  49. const endLabel = this.endPanel.getChildByPath('Sprite/EndLabel');
  50. if (endLabel) {
  51. const labelComponent = endLabel.getComponent(Label);
  52. if (labelComponent) {
  53. labelComponent.string = text;
  54. console.log(`[UIStateManager] 设置EndLabel文本为: ${text}`);
  55. } else {
  56. console.warn('[UIStateManager] 未找到EndLabel的Label组件');
  57. }
  58. } else {
  59. console.warn('[UIStateManager] 未找到EndLabel节点路径: Sprite/EndLabel');
  60. }
  61. }
  62. private onGameSuccess() {
  63. // 如果被禁用响应游戏事件,则跳过
  64. if (!this.shouldRespondToGameEvents) {
  65. console.log('[UIStateManager] 已禁用游戏事件响应,跳过GAME_SUCCESS处理');
  66. return;
  67. }
  68. // 奖励处理已迁移到GameEnd.ts,这里只处理EndLabel显示和面板显示
  69. if (this.endPanel) {
  70. this.setEndLabelText('SUCCESS');
  71. this.endPanel.active = true;
  72. console.log('[UIStateManager] 显示GameEnd面板 - SUCCESS');
  73. }
  74. }
  75. private onGameDefeat() {
  76. // 如果被禁用响应游戏事件,则跳过
  77. if (!this.shouldRespondToGameEvents) {
  78. console.log('[UIStateManager] 已禁用游戏事件响应,跳过GAME_DEFEAT处理');
  79. return;
  80. }
  81. // 奖励处理已迁移到GameEnd.ts,这里只处理EndLabel显示和面板显示
  82. if (this.endPanel) {
  83. this.setEndLabelText('DEFEAT');
  84. this.endPanel.active = true;
  85. console.log('[UIStateManager] 显示GameEnd面板 - DEFEAT');
  86. }
  87. }
  88. /** 对外接口 */
  89. public closeAllPanels() {
  90. console.log('[UIStateManager] 重置UI状态,关闭所有面板');
  91. // 关闭游戏结束面板
  92. if (this.endPanel) {
  93. this.endPanel.active = false;
  94. console.log('[UIStateManager] 已关闭GameEnd面板');
  95. }
  96. // 暂时禁用游戏事件响应,避免与GameManager冲突
  97. this.shouldRespondToGameEvents = false;
  98. // 延迟重新启用游戏事件响应
  99. this.scheduleOnce(() => {
  100. this.shouldRespondToGameEvents = true;
  101. console.log('[UIStateManager] 游戏事件响应已重新启用');
  102. }, 1.0);
  103. }
  104. protected onDestroy() {
  105. // 清理事件监听
  106. const eventBus = EventBus.getInstance();
  107. eventBus.off(GameEvents.GAME_SUCCESS, this.onGameSuccess, this);
  108. eventBus.off(GameEvents.GAME_DEFEAT, this.onGameDefeat, this);
  109. eventBus.off(GameEvents.RESET_UI_STATES, this.closeAllPanels, this);
  110. super.onDestroy();
  111. }
  112. }