StartGame.ts 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. import { _decorator, Component, find, UITransform } from 'cc';
  2. import { LevelSessionManager } from '../Core/LevelSessionManager';
  3. import { SaveDataManager } from './SaveDataManager';
  4. import EventBus, { GameEvents } from '../Core/EventBus';
  5. import { GameManager } from './GameManager';
  6. const { ccclass } = _decorator;
  7. /**
  8. * 游戏启动管理器
  9. * 负责统一处理游戏启动流程:生成方块选择 → 播放diban动画 → 确认开始游戏,并加载游戏状态
  10. * 不区分首次游戏和重启游戏,统一按照流程进行
  11. *
  12. * 注意:这个类主要提供静态方法,不需要挂载到场景节点上
  13. */
  14. @ccclass('StartGame')
  15. export class StartGame extends Component {
  16. private static eventListenersInitialized = false;
  17. start() {
  18. // 初始化静态事件监听器(只初始化一次)
  19. StartGame.initializeEventListeners();
  20. }
  21. onDestroy() {
  22. // 组件销毁时不移除静态事件监听,因为其他地方可能还需要使用
  23. }
  24. /**
  25. * 初始化静态事件监听器
  26. * 可以被外部调用以确保事件监听器已设置
  27. */
  28. public static initializeEventListeners() {
  29. if (StartGame.eventListenersInitialized) {
  30. return;
  31. }
  32. const eventBus = EventBus.getInstance();
  33. eventBus.on(GameEvents.GAME_START, StartGame.onGameStartEvent);
  34. eventBus.on(GameEvents.GAME_RESTART, StartGame.onGameStartEvent);
  35. StartGame.eventListenersInitialized = true;
  36. console.log('[StartGame] 静态事件监听器初始化完成');
  37. }
  38. /**
  39. * 处理游戏启动事件(统一处理首次启动和重启)
  40. */
  41. private static onGameStartEvent() {
  42. console.log('[StartGame] 接收到游戏启动事件,开始游戏启动流程');
  43. StartGame.startGameFlow();
  44. }
  45. /**
  46. * 统一的游戏启动流程
  47. * 无论是首次启动还是重启,都按照相同流程进行
  48. * 注意:不在此处清理游戏状态,清理由GameEnd UI状态监听机制负责
  49. */
  50. public static async startGameFlow() {
  51. console.log('[StartGame] 开始游戏启动流程');
  52. // 确保事件监听器已初始化
  53. StartGame.initializeEventListeners();
  54. const eventBus = EventBus.getInstance();
  55. // 1. 初始化游戏数据
  56. console.log('[StartGame] 初始化游戏数据');
  57. await StartGame.initializeGameData();
  58. // 2. 初始化GameBlockSelection确认回调(避免场景加载时过早设置)
  59. console.log('[StartGame] 设置GameBlockSelection确认回调');
  60. const gameManager = GameManager.getInstance();
  61. if (gameManager) {
  62. (gameManager as any).initGameBlockSelection();
  63. console.log('[StartGame] GameBlockSelection确认回调设置完成');
  64. }
  65. // 3. 生成初始方块
  66. console.log('[StartGame] 生成初始方块');
  67. const blockSelectionUINode = find('Canvas/GameLevelUI/BlockSelectionUI');
  68. if (blockSelectionUINode) {
  69. const gameBlockSelection = blockSelectionUINode.getComponent('GameBlockSelection');
  70. if (gameBlockSelection) {
  71. (gameBlockSelection as any).generateBlockSelection();
  72. console.log('[StartGame] 初始方块生成完成');
  73. } else {
  74. console.warn('[StartGame] GameBlockSelection组件未找到');
  75. }
  76. } else {
  77. console.warn('[StartGame] diban容器节点未找到');
  78. }
  79. // 4. 播放diban上移动画和镜头下移动画
  80. console.log('[StartGame] 播放diban上移动画和镜头下移动画');
  81. const cameraNode = find('Canvas/Camera');
  82. if (cameraNode) {
  83. const gameStartMove = cameraNode.getComponent('GameStartMove');
  84. if (gameStartMove) {
  85. (gameStartMove as any).slideUpFromBottom(0.3);
  86. console.log('[StartGame] diban上移动画和镜头下移动画已启动');
  87. } else {
  88. console.warn('[StartGame] GameStartMove组件未找到');
  89. }
  90. } else {
  91. console.warn('[StartGame] Camera节点未找到');
  92. }
  93. console.log('[StartGame] 游戏启动流程完成');
  94. }
  95. /**
  96. * 初始化游戏数据
  97. */
  98. private static async initializeGameData() {
  99. // 清理并重新初始化关卡会话数据
  100. LevelSessionManager.inst.clear();
  101. // 初始化存档管理器
  102. const saveDataManager = SaveDataManager.getInstance();
  103. await saveDataManager.initialize();
  104. // 重新初始化LevelSessionManager,设置sessionCoins为45
  105. LevelSessionManager.inst.initialize(
  106. saveDataManager.getCurrentLevel(),
  107. 100 // 默认墙血量,可以根据需要调整
  108. );
  109. // 计算游戏区域边界
  110. StartGame.calculateGameBounds();
  111. console.log('[StartGame] 游戏数据初始化完成,sessionCoins已设置为45');
  112. // 先重置能量为0
  113. const eventBus = EventBus.getInstance();
  114. eventBus.emit(GameEvents.RESET_ENERGY_SYSTEM);
  115. console.log('[StartGame] 发送能量重置事件');
  116. // 延迟加载关卡配置,确保能量重置先执行
  117. setTimeout(async () => {
  118. // 获取GameManager实例并加载关卡配置
  119. const gameManagerNode = find('GameManager');
  120. if (gameManagerNode) {
  121. const gameManager = gameManagerNode.getComponent(GameManager);
  122. if (gameManager && gameManager.loadCurrentLevelConfig) {
  123. await gameManager.loadCurrentLevelConfig();
  124. console.log('[StartGame] 关卡配置加载完成');
  125. }
  126. }
  127. }, 100);
  128. }
  129. /**
  130. * 计算游戏区域边界
  131. */
  132. private static calculateGameBounds() {
  133. const canvas = find('Canvas');
  134. if (!canvas) {
  135. console.warn('[StartGame] 未找到Canvas节点');
  136. return;
  137. }
  138. const canvasUI = canvas.getComponent(UITransform);
  139. if (!canvasUI) {
  140. console.warn('[StartGame] Canvas节点缺少UITransform组件');
  141. return;
  142. }
  143. const screenWidth = canvasUI.width;
  144. const screenHeight = canvasUI.height;
  145. const worldPos = canvas.worldPosition;
  146. const gameBounds = {
  147. left: worldPos.x - screenWidth / 2,
  148. right: worldPos.x + screenWidth / 2,
  149. bottom: worldPos.y - screenHeight / 2,
  150. top: worldPos.y + screenHeight / 2
  151. };
  152. console.log('[StartGame] 游戏区域边界计算完成:', gameBounds);
  153. }
  154. /**
  155. * 通过事件系统重置能量值
  156. */
  157. public static resetEnergy() {
  158. const eventBus = EventBus.getInstance();
  159. eventBus.emit(GameEvents.RESET_ENERGY_SYSTEM);
  160. console.log('[StartGame] 发送能量重置事件');
  161. }
  162. }