StartGame.ts 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  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. 设置BlockManager的gameStarted标志(在生成方块之前设置)
  66. console.log('[StartGame] 设置BlockManager的gameStarted标志');
  67. const blockManagerNode = find('Canvas/GameLevelUI/BlockController');
  68. if (blockManagerNode) {
  69. const blockManager = blockManagerNode.getComponent('BlockManager');
  70. if (blockManager) {
  71. (blockManager as any).onGameStart();
  72. console.log('[StartGame] BlockManager gameStarted标志已设置');
  73. } else {
  74. console.warn('[StartGame] BlockManager组件未找到');
  75. }
  76. } else {
  77. console.warn('[StartGame] BlockManager节点未找到');
  78. }
  79. // 4. 生成初始方块(在gameStarted标志设置之后)
  80. console.log('[StartGame] 生成初始方块');
  81. const blockSelectionUINode = find('Canvas/GameLevelUI/BlockSelectionUI');
  82. if (blockSelectionUINode) {
  83. const gameBlockSelection = blockSelectionUINode.getComponent('GameBlockSelection');
  84. if (gameBlockSelection) {
  85. (gameBlockSelection as any).generateBlockSelection();
  86. console.log('[StartGame] 初始方块生成完成');
  87. } else {
  88. console.warn('[StartGame] GameBlockSelection组件未找到');
  89. }
  90. } else {
  91. console.warn('[StartGame] diban容器节点未找到');
  92. }
  93. // 5. 播放diban上移动画和镜头下移动画
  94. console.log('[StartGame] 播放diban上移动画和镜头下移动画');
  95. const cameraNode = find('Canvas/Camera');
  96. if (cameraNode) {
  97. const gameStartMove = cameraNode.getComponent('GameStartMove');
  98. if (gameStartMove) {
  99. (gameStartMove as any).slideUpFromBottom(0.3);
  100. console.log('[StartGame] diban上移动画和镜头下移动画已启动');
  101. } else {
  102. console.warn('[StartGame] GameStartMove组件未找到');
  103. }
  104. } else {
  105. console.warn('[StartGame] Camera节点未找到');
  106. }
  107. console.log('[StartGame] 游戏启动流程完成');
  108. }
  109. /**
  110. * 初始化游戏数据
  111. */
  112. private static async initializeGameData() {
  113. // 清理并重新初始化关卡会话数据
  114. LevelSessionManager.inst.clear();
  115. // 初始化存档管理器
  116. const saveDataManager = SaveDataManager.getInstance();
  117. await saveDataManager.initialize();
  118. // 重新初始化LevelSessionManager,从关卡配置读取initialCoins
  119. await LevelSessionManager.inst.initialize(
  120. saveDataManager.getCurrentLevel(),
  121. 100 // 默认墙血量,可以根据需要调整
  122. );
  123. // 计算游戏区域边界
  124. StartGame.calculateGameBounds();
  125. console.log('[StartGame] 游戏数据初始化完成,sessionCoins已从关卡配置读取');
  126. // 重置游戏相关组件
  127. const eventBus = EventBus.getInstance();
  128. // 重置球控制器,清理上一关可能残留的球
  129. eventBus.emit(GameEvents.RESET_BALL_CONTROLLER);
  130. console.log('[StartGame] 发送球控制器重置事件,清理上一关残留的球');
  131. // 先重置能量为0
  132. eventBus.emit(GameEvents.RESET_ENERGY_SYSTEM);
  133. console.log('[StartGame] 发送能量重置事件');
  134. // 延迟加载关卡配置,确保能量重置先执行
  135. setTimeout(async () => {
  136. // 获取GameManager实例并加载关卡配置
  137. const gameManagerNode = find('GameManager');
  138. if (gameManagerNode) {
  139. const gameManager = gameManagerNode.getComponent(GameManager);
  140. if (gameManager && gameManager.loadCurrentLevelConfig) {
  141. await gameManager.loadCurrentLevelConfig();
  142. console.log('[StartGame] 关卡配置加载完成');
  143. }
  144. }
  145. }, 100);
  146. }
  147. /**
  148. * 计算游戏区域边界
  149. */
  150. private static calculateGameBounds() {
  151. const canvas = find('Canvas');
  152. if (!canvas) {
  153. console.warn('[StartGame] 未找到Canvas节点');
  154. return;
  155. }
  156. const canvasUI = canvas.getComponent(UITransform);
  157. if (!canvasUI) {
  158. console.warn('[StartGame] Canvas节点缺少UITransform组件');
  159. return;
  160. }
  161. const screenWidth = canvasUI.width;
  162. const screenHeight = canvasUI.height;
  163. const worldPos = canvas.worldPosition;
  164. const gameBounds = {
  165. left: worldPos.x - screenWidth / 2,
  166. right: worldPos.x + screenWidth / 2,
  167. bottom: worldPos.y - screenHeight / 2,
  168. top: worldPos.y + screenHeight / 2
  169. };
  170. console.log('[StartGame] 游戏区域边界计算完成:', gameBounds);
  171. }
  172. /**
  173. * 通过事件系统重置能量值
  174. */
  175. public static resetEnergy() {
  176. const eventBus = EventBus.getInstance();
  177. eventBus.emit(GameEvents.RESET_ENERGY_SYSTEM);
  178. console.log('[StartGame] 发送能量重置事件');
  179. }
  180. }