StartGame.ts 8.4 KB

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