UIStateManager.ts 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  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. if (this.endPanel) {
  69. this.endPanel.active = true;
  70. this.setEndLabelText('SUCCESS');
  71. }
  72. }
  73. private onGameDefeat() {
  74. // 如果被禁用响应游戏事件,则跳过
  75. if (!this.shouldRespondToGameEvents) {
  76. console.log('[UIStateManager] 已禁用游戏事件响应,跳过GAME_DEFEAT处理');
  77. return;
  78. }
  79. if (this.endPanel) {
  80. this.endPanel.active = true;
  81. this.setEndLabelText('DEFEAT');
  82. }
  83. }
  84. /** 对外接口 */
  85. public closeAllPanels() {
  86. console.log('[UIStateManager] 重置UI状态,关闭所有面板');
  87. // 关闭游戏结束面板
  88. if (this.endPanel) {
  89. this.endPanel.active = false;
  90. console.log('[UIStateManager] 已关闭GameEnd面板');
  91. }
  92. // 暂时禁用游戏事件响应,避免与GameManager冲突
  93. this.shouldRespondToGameEvents = false;
  94. // 延迟重新启用游戏事件响应
  95. this.scheduleOnce(() => {
  96. this.shouldRespondToGameEvents = true;
  97. console.log('[UIStateManager] 游戏事件响应已重新启用');
  98. }, 1.0);
  99. }
  100. protected onDestroy() {
  101. // 清理事件监听
  102. const eventBus = EventBus.getInstance();
  103. eventBus.off(GameEvents.GAME_SUCCESS, this.onGameSuccess, this);
  104. eventBus.off(GameEvents.GAME_DEFEAT, this.onGameDefeat, this);
  105. eventBus.off(GameEvents.RESET_UI_STATES, this.closeAllPanels, this);
  106. super.onDestroy();
  107. }
  108. }