Files
shooter-demo/client-cocos/assets/scripts/Modules/Pinball/PinballManager.ts
2025-11-28 18:10:10 +08:00

400 lines
11 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* PinballManager - Pinball模块主控制器
* 负责整个Pinball模块的生命周期管理和模式切换
*/
import { _decorator, Camera, Component, director, Director, game, Game, Node, Scene } from 'cc';
import { EventBus } from './Core/EventBus';
import { GameState, PinballConfig } from './Core/GameData';
import { StandaloneMode } from './GameModes/StandaloneMode';
const { ccclass, property } = _decorator;
export enum PinballMode {
STANDALONE = 'standalone',
CLIENT_MULTIPLAYER = 'client-multiplayer',
SERVER_MULTIPLAYER = 'server-multiplayer'
}
@ccclass('PinballManager')
export class PinballManager extends Component {
@property({
type: Node,
tooltip: "主相机节点,用于渲染游戏画面"
})
cameraNode: Node = null;
@property({
type: Node,
tooltip: "渲染容器节点,所有游戏对象将在此节点下渲染"
})
renderContainer: Node = null;
@property({
type: Node,
tooltip: "UI容器节点用于显示游戏UI界面"
})
uiContainer: Node = null;
@property({
tooltip: "启动时的默认游戏模式"
})
defaultMode: PinballMode = PinballMode.STANDALONE;
@property({
tooltip: "是否在启动时自动开始游戏"
})
autoStart: boolean = true;
@property({
tooltip: "调试模式,启用详细日志"
})
debugMode: boolean = true;
// 核心系统
private eventBus: EventBus = null;
private currentMode: PinballMode = null;
private currentGameMode: Component = null;
private mainCamera: Camera = null;
// 游戏状态
private isInitialized: boolean = false;
private isPaused: boolean = false;
private gameConfig: PinballConfig = null;
/**
* 启动 PinballManager
* 必须在配置应用后调用
*/
async Start(): Promise<boolean> {
this.log('[PinballManager] Start 开始');
try {
// 初始化事件总线
this.eventBus = EventBus.getInstance();
// 验证必需的节点
if (!this.validateRequiredNodes()) {
console.error('[PinballManager] 必需节点验证失败');
return false;
}
// 获取主相机
this.initializeCamera();
// 创建默认配置
this.createDefaultConfig();
// 注册全局事件监听器
this.registerGlobalEvents();
// 初始化完成
this.isInitialized = true;
this.log('[PinballManager] 初始化完成');
this.log('[PinballManager] Start 完成');
return true;
} catch (error) {
console.error('[PinballManager] Start 过程中发生错误:', error);
return false;
}
}
/**
* 停止 PinballManager
*/
Stop(): void {
this.log('[PinballManager] Stop 开始');
this.cleanup();
this.isInitialized = false;
this.log('[PinballManager] Stop 完成');
}
// 保留 onDestroy 作为安全清理
onDestroy() {
this.Stop();
}
/**
* 验证必需的节点
*/
private validateRequiredNodes(): boolean {
if (!this.cameraNode) {
console.error('[PinballManager] cameraNode 未设置');
return false;
}
if (!this.renderContainer) {
console.error('[PinballManager] renderContainer 未设置');
return false;
}
return true;
}
/**
* 初始化相机
*/
private initializeCamera(): void {
this.mainCamera = this.cameraNode.getComponent(Camera);
if (!this.mainCamera) {
console.error('[PinballManager] 主相机组件未找到');
return;
}
this.log('主相机初始化完成');
}
/**
* 创建默认配置
*/
private createDefaultConfig(): void {
this.gameConfig = {
mode: this.defaultMode,
physicsSettings: {
gravity: { x: 0, y: -9.81 },
timeStep: 1 / 60
},
renderSettings: {
enableEffects: true,
maxParticles: 500
},
wasmPath: 'assets/wasm/pinball_physics.wasm'
};
this.log('默认配置创建完成', this.gameConfig);
}
/**
* 注册全局事件监听器
*/
private registerGlobalEvents(): void {
// 监听场景切换事件 - Cocos Creator 3.x 中使用静态常量
director.on(Director.EVENT_BEFORE_SCENE_LAUNCH, this.onSceneChange, this);
// 监听游戏暂停/恢复 - Cocos Creator 3.x 中使用game事件
game.on(Game.EVENT_HIDE, this.onGamePause, this);
game.on(Game.EVENT_SHOW, this.onGameResume, this);
this.log('全局事件监听器注册完成');
}
/**
* 启动游戏
*/
public async startGame(mode: PinballMode): Promise<boolean> {
if (!this.isInitialized) {
console.error('[PinballManager] 尚未初始化');
return false;
}
if (this.currentGameMode) {
await this.stopCurrentGame();
}
this.log(`开始启动游戏模式: ${mode}`);
try {
switch (mode) {
case PinballMode.STANDALONE:
await this.startStandaloneMode();
break;
case PinballMode.CLIENT_MULTIPLAYER:
console.warn('[PinballManager] Client Multiplayer 模式尚未实现');
return false;
case PinballMode.SERVER_MULTIPLAYER:
console.warn('[PinballManager] Server Multiplayer 模式尚未实现');
return false;
default:
console.error(`[PinballManager] 未知游戏模式: ${mode}`);
return false;
}
this.currentMode = mode;
this.gameConfig.mode = mode;
this.log(`游戏模式 ${mode} 启动成功`);
// 发送游戏开始事件
this.eventBus.emit('game.started', { mode });
return true;
} catch (error) {
console.error(`[PinballManager] 启动游戏模式 ${mode} 失败:`, error);
return false;
}
}
/**
* 启动Standalone模式
*/
private async startStandaloneMode(): Promise<void> {
// 添加StandaloneMode组件
const standaloneMode = this.node.addComponent(StandaloneMode);
// 设置所需的引用
standaloneMode.gameCamera = this.mainCamera;
standaloneMode.renderNode = this.renderContainer;
standaloneMode.boundsNode = this.renderContainer; // 简化设置
// StandaloneMode 会在 onLoad 中自动初始化
this.currentGameMode = standaloneMode;
this.log('Standalone模式启动完成');
}
/**
* 停止当前游戏模式
*/
public async stopCurrentGame(): Promise<void> {
if (!this.currentGameMode) {
return;
}
this.log(`停止当前游戏模式: ${this.currentMode}`);
// 销毁当前游戏模式组件
this.currentGameMode.destroy();
this.currentGameMode = null;
this.currentMode = null;
// 发送游戏停止事件
this.eventBus.emit('game.stopped', {});
this.log('当前游戏模式已停止');
}
/**
* 暂停游戏
*/
public pauseGame(): void {
if (this.isPaused) {
return;
}
this.isPaused = true;
this.eventBus.emit('game.paused', {});
this.log('游戏已暂停');
}
/**
* 恢复游戏
*/
public resumeGame(): void {
if (!this.isPaused) {
return;
}
this.isPaused = false;
this.eventBus.emit('game.resumed', {});
this.log('游戏已恢复');
}
/**
* 重启当前游戏
*/
public async restartGame(): Promise<boolean> {
const currentMode = this.currentMode;
if (currentMode) {
await this.stopCurrentGame();
return await this.startGame(currentMode);
}
return false;
}
/**
* 切换游戏模式
*/
public async switchMode(newMode: PinballMode): Promise<boolean> {
if (this.currentMode === newMode) {
this.log(`已经是 ${newMode} 模式`);
return true;
}
return await this.startGame(newMode);
}
/**
* 场景切换事件处理
*/
private onSceneChange(scene: Scene): void {
this.log('场景切换事件');
// 可以在此处理场景切换时的清理工作
}
/**
* 游戏暂停事件处理
*/
private onGamePause(): void {
this.pauseGame();
}
/**
* 游戏恢复事件处理
*/
private onGameResume(): void {
this.resumeGame();
}
/**
* 清理资源
*/
private cleanup(): void {
// 清理全局事件监听器
director.off(Director.EVENT_BEFORE_SCENE_LAUNCH, this.onSceneChange, this);
game.off(Game.EVENT_HIDE, this.onGamePause, this);
game.off(Game.EVENT_SHOW, this.onGameResume, this);
// 停止当前游戏
if (this.currentGameMode) {
this.stopCurrentGame();
}
this.log('PinballManager 资源清理完成');
}
/**
* 获取当前游戏状态
*/
public getGameState(): GameState | null {
if (this.currentGameMode && this.currentGameMode instanceof StandaloneMode) {
return this.currentGameMode.getGameStats() as any;
}
return null;
}
/**
* 获取游戏配置
*/
public getConfig(): PinballConfig {
return this.gameConfig;
}
/**
* 更新游戏配置
*/
public updateConfig(newConfig: Partial<PinballConfig>): void {
this.gameConfig = { ...this.gameConfig, ...newConfig };
this.log('游戏配置已更新', this.gameConfig);
}
/**
* 调试日志输出
*/
private log(message: string, data?: any): void {
if (this.debugMode) {
if (data) {
console.log(`[PinballManager] ${message}`, data);
} else {
console.log(`[PinballManager] ${message}`);
}
}
}
}