GamePause.ts 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. import { _decorator, Component, Node, RigidBody2D, find } from 'cc';
  2. import { EnemyController } from './EnemyController';
  3. import { BallController } from './BallController';
  4. import EventBus, { GameEvents } from '../Core/EventBus';
  5. const { ccclass, property } = _decorator;
  6. /**
  7. * 游戏暂停状态枚举
  8. */
  9. export enum PauseState {
  10. PLAYING = 'playing',
  11. PAUSED = 'paused'
  12. }
  13. /**
  14. * 游戏暂停管理器
  15. * 统一管理游戏的暂停和恢复逻辑
  16. */
  17. @ccclass('GamePause')
  18. export class GamePause extends Component {
  19. public static _instance: GamePause = null;
  20. // 当前暂停状态
  21. private currentState: PauseState = PauseState.PLAYING;
  22. // 暂停前保存的敌人状态
  23. private pausedEnemyStates: Map<Node, {
  24. velocity: any,
  25. angularVelocity: number,
  26. isMoving: boolean,
  27. attackTimer: number
  28. }> = new Map();
  29. // 暂停前保存的小球状态
  30. private pausedBallStates: Map<Node, {
  31. velocity: any,
  32. angularVelocity: number
  33. }> = new Map();
  34. // 是否允许小球发射子弹(暂停时禁用)
  35. private bulletFireEnabled: boolean = true;
  36. start() {
  37. // 监听游戏事件
  38. const eventBus = EventBus.getInstance();
  39. eventBus.on(GameEvents.GAME_SUCCESS, this.onGameEnd, this);
  40. eventBus.on(GameEvents.GAME_DEFEAT, this.onGameEnd, this);
  41. }
  42. /**
  43. * 暂停游戏
  44. */
  45. public pauseGame(): void {
  46. if (this.currentState === PauseState.PAUSED) {
  47. return;
  48. }
  49. console.log('GamePause: 暂停游戏');
  50. this.currentState = PauseState.PAUSED;
  51. // 禁用小球发射子弹
  52. this.bulletFireEnabled = false;
  53. // 暂停敌人
  54. this.pauseAllEnemies();
  55. // 暂停敌人生成
  56. this.pauseEnemySpawning();
  57. // 小球继续运动但不发射子弹(根据新需求)
  58. // 不调用 pauseBalls() 方法
  59. // 派发暂停事件
  60. EventBus.getInstance().emit(GameEvents.GAME_PAUSE);
  61. }
  62. /**
  63. * 恢复游戏
  64. */
  65. public resumeGame(): void {
  66. if (this.currentState === PauseState.PLAYING) {
  67. return;
  68. }
  69. console.log('GamePause: 恢复游戏');
  70. this.currentState = PauseState.PLAYING;
  71. // 启用小球发射子弹
  72. this.bulletFireEnabled = true;
  73. // 恢复敌人
  74. this.resumeAllEnemies();
  75. // 恢复敌人生成
  76. this.resumeEnemySpawning();
  77. // 恢复小球(如果之前被暂停的话)
  78. this.resumeAllBalls();
  79. // 派发恢复事件
  80. EventBus.getInstance().emit(GameEvents.GAME_RESUME);
  81. }
  82. /**
  83. * 暂停所有敌人
  84. */
  85. private pauseAllEnemies(): void {
  86. const enemyController = EnemyController.getInstance();
  87. if (!enemyController) return;
  88. const activeEnemies = enemyController.getActiveEnemies?.() || [];
  89. for (const enemy of activeEnemies) {
  90. if (!enemy || !enemy.isValid) continue;
  91. // 保存敌人状态
  92. const rigidBody = enemy.getComponent(RigidBody2D);
  93. if (rigidBody) {
  94. this.pausedEnemyStates.set(enemy, {
  95. velocity: rigidBody.linearVelocity.clone(),
  96. angularVelocity: rigidBody.angularVelocity,
  97. isMoving: true,
  98. attackTimer: 0 // 可以扩展保存攻击计时器
  99. });
  100. // 停止敌人运动
  101. rigidBody.linearVelocity.set(0, 0);
  102. rigidBody.angularVelocity = 0;
  103. rigidBody.sleep();
  104. }
  105. // 暂停敌人AI组件(如果有的话)
  106. const enemyAI = enemy.getComponent('EnemyAI');
  107. if (enemyAI && typeof (enemyAI as any).pause === 'function') {
  108. (enemyAI as any).pause();
  109. }
  110. // 暂停敌人动画(如果有的话)
  111. const animation = enemy.getComponent('Animation');
  112. if (animation && typeof (animation as any).pause === 'function') {
  113. (animation as any).pause();
  114. }
  115. }
  116. }
  117. /**
  118. * 恢复所有敌人
  119. */
  120. private resumeAllEnemies(): void {
  121. const enemyController = EnemyController.getInstance();
  122. if (!enemyController) return;
  123. const activeEnemies = enemyController.getActiveEnemies?.() || [];
  124. for (const enemy of activeEnemies) {
  125. if (!enemy || !enemy.isValid) continue;
  126. const savedState = this.pausedEnemyStates.get(enemy);
  127. if (savedState) {
  128. const rigidBody = enemy.getComponent(RigidBody2D);
  129. if (rigidBody) {
  130. // 恢复敌人运动
  131. rigidBody.wakeUp();
  132. rigidBody.linearVelocity = savedState.velocity;
  133. rigidBody.angularVelocity = savedState.angularVelocity;
  134. }
  135. }
  136. // 恢复敌人AI组件
  137. const enemyAI = enemy.getComponent('EnemyAI');
  138. if (enemyAI && typeof (enemyAI as any).resume === 'function') {
  139. (enemyAI as any).resume();
  140. }
  141. // 恢复敌人动画
  142. const animation = enemy.getComponent('Animation');
  143. if (animation && typeof (animation as any).resume === 'function') {
  144. (animation as any).resume();
  145. }
  146. }
  147. // 清空保存的状态
  148. this.pausedEnemyStates.clear();
  149. }
  150. /**
  151. * 暂停敌人生成
  152. */
  153. private pauseEnemySpawning(): void {
  154. const enemyController = EnemyController.getInstance();
  155. if (enemyController && enemyController.pauseSpawning) {
  156. enemyController.pauseSpawning();
  157. }
  158. }
  159. /**
  160. * 恢复敌人生成
  161. */
  162. private resumeEnemySpawning(): void {
  163. const enemyController = EnemyController.getInstance();
  164. if (enemyController && enemyController.resumeSpawning) {
  165. enemyController.resumeSpawning();
  166. }
  167. }
  168. /**
  169. * 暂停所有小球
  170. */
  171. private pauseAllBalls(): void {
  172. // 查找所有小球控制器
  173. const ballControllers = this.findAllBallControllers();
  174. for (const ballController of ballControllers) {
  175. if (ballController && ballController.pauseBall) {
  176. ballController.pauseBall();
  177. }
  178. }
  179. }
  180. /**
  181. * 恢复所有小球
  182. */
  183. private resumeAllBalls(): void {
  184. // 查找所有小球控制器
  185. const ballControllers = this.findAllBallControllers();
  186. for (const ballController of ballControllers) {
  187. if (ballController && ballController.resumeBall) {
  188. ballController.resumeBall();
  189. }
  190. }
  191. }
  192. /**
  193. * 查找所有小球控制器
  194. */
  195. private findAllBallControllers(): BallController[] {
  196. const controllers: BallController[] = [];
  197. // 主要的小球控制器
  198. const mainBallControllerNode = find('Canvas/GameLevelUI/BallController');
  199. if (mainBallControllerNode) {
  200. const controller = mainBallControllerNode.getComponent(BallController);
  201. if (controller) {
  202. controllers.push(controller);
  203. }
  204. }
  205. // 可以扩展查找其他小球控制器
  206. // 例如:多球模式下的额外控制器
  207. return controllers;
  208. }
  209. /**
  210. * 游戏结束时的处理
  211. */
  212. private onGameEnd(): void {
  213. this.pauseGame();
  214. }
  215. /**
  216. * 检查是否为暂停状态
  217. */
  218. public isPaused(): boolean {
  219. return this.currentState === PauseState.PAUSED;
  220. }
  221. /**
  222. * 检查是否允许发射子弹
  223. */
  224. public isBulletFireEnabled(): boolean {
  225. return this.bulletFireEnabled;
  226. }
  227. /**
  228. * 获取当前暂停状态
  229. */
  230. public getCurrentState(): PauseState {
  231. return this.currentState;
  232. }
  233. /**
  234. * 强制设置暂停状态(谨慎使用)
  235. */
  236. public forceSetState(state: PauseState): void {
  237. this.currentState = state;
  238. this.bulletFireEnabled = (state === PauseState.PLAYING);
  239. }
  240. /**
  241. * 获取单例实例
  242. */
  243. public static getInstance(): GamePause {
  244. if (!GamePause._instance) {
  245. // 创建节点和组件
  246. const gamePauseNode = new Node('GamePause');
  247. GamePause._instance = gamePauseNode.addComponent(GamePause);
  248. // 将节点添加到场景中(不销毁)
  249. const scene = find('Canvas');
  250. if (scene) {
  251. scene.addChild(gamePauseNode);
  252. }
  253. }
  254. return GamePause._instance;
  255. }
  256. onDestroy() {
  257. // 清理事件监听
  258. const eventBus = EventBus.getInstance();
  259. eventBus.off(GameEvents.GAME_SUCCESS, this.onGameEnd, this);
  260. eventBus.off(GameEvents.GAME_DEFEAT, this.onGameEnd, this);
  261. // 清空状态
  262. this.pausedEnemyStates.clear();
  263. this.pausedBallStates.clear();
  264. GamePause._instance = null;
  265. }
  266. }