|
|
@@ -0,0 +1,322 @@
|
|
|
+import { _decorator, Component, Node, RigidBody2D, find } from 'cc';
|
|
|
+import { EnemyController } from './EnemyController';
|
|
|
+import { BallController } from './BallController';
|
|
|
+import EventBus, { GameEvents } from '../Core/EventBus';
|
|
|
+
|
|
|
+const { ccclass, property } = _decorator;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 游戏暂停状态枚举
|
|
|
+ */
|
|
|
+export enum PauseState {
|
|
|
+ PLAYING = 'playing',
|
|
|
+ PAUSED = 'paused'
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 游戏暂停管理器
|
|
|
+ * 统一管理游戏的暂停和恢复逻辑
|
|
|
+ */
|
|
|
+@ccclass('GamePause')
|
|
|
+export class GamePause extends Component {
|
|
|
+ public static _instance: GamePause = null;
|
|
|
+
|
|
|
+ // 当前暂停状态
|
|
|
+ private currentState: PauseState = PauseState.PLAYING;
|
|
|
+
|
|
|
+ // 暂停前保存的敌人状态
|
|
|
+ private pausedEnemyStates: Map<Node, {
|
|
|
+ velocity: any,
|
|
|
+ angularVelocity: number,
|
|
|
+ isMoving: boolean,
|
|
|
+ attackTimer: number
|
|
|
+ }> = new Map();
|
|
|
+
|
|
|
+ // 暂停前保存的小球状态
|
|
|
+ private pausedBallStates: Map<Node, {
|
|
|
+ velocity: any,
|
|
|
+ angularVelocity: number
|
|
|
+ }> = new Map();
|
|
|
+
|
|
|
+ // 是否允许小球发射子弹(暂停时禁用)
|
|
|
+ private bulletFireEnabled: boolean = true;
|
|
|
+
|
|
|
+ start() {
|
|
|
+ // 监听游戏事件
|
|
|
+ const eventBus = EventBus.getInstance();
|
|
|
+ eventBus.on(GameEvents.GAME_SUCCESS, this.onGameEnd, this);
|
|
|
+ eventBus.on(GameEvents.GAME_DEFEAT, this.onGameEnd, this);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 暂停游戏
|
|
|
+ */
|
|
|
+ public pauseGame(): void {
|
|
|
+ if (this.currentState === PauseState.PAUSED) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ console.log('GamePause: 暂停游戏');
|
|
|
+ this.currentState = PauseState.PAUSED;
|
|
|
+
|
|
|
+ // 禁用小球发射子弹
|
|
|
+ this.bulletFireEnabled = false;
|
|
|
+
|
|
|
+ // 暂停敌人
|
|
|
+ this.pauseAllEnemies();
|
|
|
+
|
|
|
+ // 暂停敌人生成
|
|
|
+ this.pauseEnemySpawning();
|
|
|
+
|
|
|
+ // 小球继续运动但不发射子弹(根据新需求)
|
|
|
+ // 不调用 pauseBalls() 方法
|
|
|
+
|
|
|
+ // 派发暂停事件
|
|
|
+ EventBus.getInstance().emit(GameEvents.GAME_PAUSE);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 恢复游戏
|
|
|
+ */
|
|
|
+ public resumeGame(): void {
|
|
|
+ if (this.currentState === PauseState.PLAYING) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ console.log('GamePause: 恢复游戏');
|
|
|
+ this.currentState = PauseState.PLAYING;
|
|
|
+
|
|
|
+ // 启用小球发射子弹
|
|
|
+ this.bulletFireEnabled = true;
|
|
|
+
|
|
|
+ // 恢复敌人
|
|
|
+ this.resumeAllEnemies();
|
|
|
+
|
|
|
+ // 恢复敌人生成
|
|
|
+ this.resumeEnemySpawning();
|
|
|
+
|
|
|
+ // 恢复小球(如果之前被暂停的话)
|
|
|
+ this.resumeAllBalls();
|
|
|
+
|
|
|
+ // 派发恢复事件
|
|
|
+ EventBus.getInstance().emit(GameEvents.GAME_RESUME);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 暂停所有敌人
|
|
|
+ */
|
|
|
+ private pauseAllEnemies(): void {
|
|
|
+ const enemyController = EnemyController.getInstance();
|
|
|
+ if (!enemyController) return;
|
|
|
+
|
|
|
+ const activeEnemies = enemyController.getActiveEnemies?.() || [];
|
|
|
+
|
|
|
+ for (const enemy of activeEnemies) {
|
|
|
+ if (!enemy || !enemy.isValid) continue;
|
|
|
+
|
|
|
+ // 保存敌人状态
|
|
|
+ const rigidBody = enemy.getComponent(RigidBody2D);
|
|
|
+ if (rigidBody) {
|
|
|
+ this.pausedEnemyStates.set(enemy, {
|
|
|
+ velocity: rigidBody.linearVelocity.clone(),
|
|
|
+ angularVelocity: rigidBody.angularVelocity,
|
|
|
+ isMoving: true,
|
|
|
+ attackTimer: 0 // 可以扩展保存攻击计时器
|
|
|
+ });
|
|
|
+
|
|
|
+ // 停止敌人运动
|
|
|
+ rigidBody.linearVelocity.set(0, 0);
|
|
|
+ rigidBody.angularVelocity = 0;
|
|
|
+ rigidBody.sleep();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 暂停敌人AI组件(如果有的话)
|
|
|
+ const enemyAI = enemy.getComponent('EnemyAI');
|
|
|
+ if (enemyAI && typeof (enemyAI as any).pause === 'function') {
|
|
|
+ (enemyAI as any).pause();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 暂停敌人动画(如果有的话)
|
|
|
+ const animation = enemy.getComponent('Animation');
|
|
|
+ if (animation && typeof (animation as any).pause === 'function') {
|
|
|
+ (animation as any).pause();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 恢复所有敌人
|
|
|
+ */
|
|
|
+ private resumeAllEnemies(): void {
|
|
|
+ const enemyController = EnemyController.getInstance();
|
|
|
+ if (!enemyController) return;
|
|
|
+
|
|
|
+ const activeEnemies = enemyController.getActiveEnemies?.() || [];
|
|
|
+
|
|
|
+ for (const enemy of activeEnemies) {
|
|
|
+ if (!enemy || !enemy.isValid) continue;
|
|
|
+
|
|
|
+ const savedState = this.pausedEnemyStates.get(enemy);
|
|
|
+ if (savedState) {
|
|
|
+ const rigidBody = enemy.getComponent(RigidBody2D);
|
|
|
+ if (rigidBody) {
|
|
|
+ // 恢复敌人运动
|
|
|
+ rigidBody.wakeUp();
|
|
|
+ rigidBody.linearVelocity = savedState.velocity;
|
|
|
+ rigidBody.angularVelocity = savedState.angularVelocity;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 恢复敌人AI组件
|
|
|
+ const enemyAI = enemy.getComponent('EnemyAI');
|
|
|
+ if (enemyAI && typeof (enemyAI as any).resume === 'function') {
|
|
|
+ (enemyAI as any).resume();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 恢复敌人动画
|
|
|
+ const animation = enemy.getComponent('Animation');
|
|
|
+ if (animation && typeof (animation as any).resume === 'function') {
|
|
|
+ (animation as any).resume();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 清空保存的状态
|
|
|
+ this.pausedEnemyStates.clear();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 暂停敌人生成
|
|
|
+ */
|
|
|
+ private pauseEnemySpawning(): void {
|
|
|
+ const enemyController = EnemyController.getInstance();
|
|
|
+ if (enemyController && enemyController.pauseSpawning) {
|
|
|
+ enemyController.pauseSpawning();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 恢复敌人生成
|
|
|
+ */
|
|
|
+ private resumeEnemySpawning(): void {
|
|
|
+ const enemyController = EnemyController.getInstance();
|
|
|
+ if (enemyController && enemyController.resumeSpawning) {
|
|
|
+ enemyController.resumeSpawning();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 暂停所有小球
|
|
|
+ */
|
|
|
+ private pauseAllBalls(): void {
|
|
|
+ // 查找所有小球控制器
|
|
|
+ const ballControllers = this.findAllBallControllers();
|
|
|
+
|
|
|
+ for (const ballController of ballControllers) {
|
|
|
+ if (ballController && ballController.pauseBall) {
|
|
|
+ ballController.pauseBall();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 恢复所有小球
|
|
|
+ */
|
|
|
+ private resumeAllBalls(): void {
|
|
|
+ // 查找所有小球控制器
|
|
|
+ const ballControllers = this.findAllBallControllers();
|
|
|
+
|
|
|
+ for (const ballController of ballControllers) {
|
|
|
+ if (ballController && ballController.resumeBall) {
|
|
|
+ ballController.resumeBall();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 查找所有小球控制器
|
|
|
+ */
|
|
|
+ private findAllBallControllers(): BallController[] {
|
|
|
+ const controllers: BallController[] = [];
|
|
|
+
|
|
|
+ // 主要的小球控制器
|
|
|
+ const mainBallControllerNode = find('Canvas/GameLevelUI/BallController');
|
|
|
+ if (mainBallControllerNode) {
|
|
|
+ const controller = mainBallControllerNode.getComponent(BallController);
|
|
|
+ if (controller) {
|
|
|
+ controllers.push(controller);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 可以扩展查找其他小球控制器
|
|
|
+ // 例如:多球模式下的额外控制器
|
|
|
+
|
|
|
+ return controllers;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 游戏结束时的处理
|
|
|
+ */
|
|
|
+ private onGameEnd(): void {
|
|
|
+ this.pauseGame();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 检查是否为暂停状态
|
|
|
+ */
|
|
|
+ public isPaused(): boolean {
|
|
|
+ return this.currentState === PauseState.PAUSED;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 检查是否允许发射子弹
|
|
|
+ */
|
|
|
+ public isBulletFireEnabled(): boolean {
|
|
|
+ return this.bulletFireEnabled;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取当前暂停状态
|
|
|
+ */
|
|
|
+ public getCurrentState(): PauseState {
|
|
|
+ return this.currentState;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 强制设置暂停状态(谨慎使用)
|
|
|
+ */
|
|
|
+ public forceSetState(state: PauseState): void {
|
|
|
+ this.currentState = state;
|
|
|
+ this.bulletFireEnabled = (state === PauseState.PLAYING);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取单例实例
|
|
|
+ */
|
|
|
+ public static getInstance(): GamePause {
|
|
|
+ if (!GamePause._instance) {
|
|
|
+ // 创建节点和组件
|
|
|
+ const gamePauseNode = new Node('GamePause');
|
|
|
+ GamePause._instance = gamePauseNode.addComponent(GamePause);
|
|
|
+
|
|
|
+ // 将节点添加到场景中(不销毁)
|
|
|
+ const scene = find('Canvas');
|
|
|
+ if (scene) {
|
|
|
+ scene.addChild(gamePauseNode);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return GamePause._instance;
|
|
|
+ }
|
|
|
+
|
|
|
+ onDestroy() {
|
|
|
+ // 清理事件监听
|
|
|
+ const eventBus = EventBus.getInstance();
|
|
|
+ eventBus.off(GameEvents.GAME_SUCCESS, this.onGameEnd, this);
|
|
|
+ eventBus.off(GameEvents.GAME_DEFEAT, this.onGameEnd, this);
|
|
|
+
|
|
|
+ // 清空状态
|
|
|
+ this.pausedEnemyStates.clear();
|
|
|
+ this.pausedBallStates.clear();
|
|
|
+
|
|
|
+ GamePause._instance = null;
|
|
|
+ }
|
|
|
+}
|