# 应用状态机 (App/AppStatus) ## 📋 模块概述 管理应用的整体状态流转,包括启动、登录、游戏等状态,基于 Framework/FSM 实现。 ## 🎯 核心特性 - ✅ 应用状态流转管理 - ✅ 网络初始化 - ✅ 登录流程 - ✅ 游戏状态管理 - ✅ 状态生命周期 - ✅ 服务器消息监听 ## 🗂️ 文件结构 ``` App/AppStatus/ ├── AppStatusManager.ts # 应用状态管理器 ├── AppStatusBoot.ts # 启动状态 ├── AppStatusLogin.ts # 登录状态 └── AppStatusGame.ts # 游戏状态 ``` ## 🔄 状态流转图 ``` [启动 Boot] → [登录 Login] → [游戏 Game] ↑ ↓ ↓ └────────────┴──────────────┘ (退出/死亡返回登录) ``` ## 📘 核心类详解 ### AppStatusManager - 应用状态管理器 **职责**: 管理应用的整体状态流转 ```typescript class AppStatusManager { private _fsm: FSM; // 底层状态机 // 获取单例 static getInstance(): AppStatusManager; // 启动应用(从 Boot 状态开始) start(): void; // 切换状态 changeState(stateName: string, params?: any): void; // 获取当前状态名称 getCurrentStateName(): string | null; // 获取当前状态实例 getCurrentState(): any; // 更新状态机(在主循环中调用) update(dt: number): void; // 获取底层 FSM 实例 getFSM(): FSM; // 销毁管理器 destroy(): void; } ``` ### AppStatusBoot - 启动状态 **职责**: 初始化网络管理器并连接服务器 ```typescript class AppStatusBoot extends BaseState { constructor(fsm: FSM); // 进入启动状态 async onEnter(params?: any): Promise; // 初始化并连接网络 private async initAndConnectNet(): Promise; // 退出启动状态 onExit(): void; } ``` **执行流程**: 1. 设置服务协议 2. 初始化网络配置 3. 监听网络事件 4. 连接服务器 5. 连接成功后切换到登录状态 ### AppStatusLogin - 登录状态 **职责**: 显示登录界面,处理登录逻辑 ```typescript class AppStatusLogin extends BaseState { constructor(fsm: FSM); // 进入登录状态 async onEnter(params?: any): Promise; // 显示登录 UI private async showLoginUI(): Promise; // 退出登录状态 onExit(): void; } ``` **执行流程**: 1. 通过 UIMgr 加载并显示登录 UI 2. 等待用户输入账号并点击登录 3. UILogin 调用 NetManager 发送登录请求 4. 登录成功后切换到游戏状态 ### AppStatusGame - 游戏状态 **职责**: 游戏主循环,处理游戏逻辑和服务器消息 ```typescript class AppStatusGame extends BaseState { private _player: any; // 玩家信息 private _isNewPlayer: boolean; // 是否新玩家 private _isPaused: boolean; // 是否暂停 constructor(fsm: FSM); // 进入游戏状态 async onEnter(params?: any): Promise; // 加载游戏场景 private async loadGameScene(): Promise; // 初始化游戏 private async initGame(): Promise; // 监听服务器广播消息 private listenServerMessages(): void; // 开始游戏 private startGame(): void; // 游戏主循环 onUpdate(dt: number): void; // 暂停游戏 pauseGame(): void; // 恢复游戏 resumeGame(): void; // 玩家死亡 private onPlayerDeath(): void; // 退出游戏(返回登录) quitGame(): void; // 退出游戏状态 onExit(): void; } ``` **执行流程**: 1. 接收玩家信息 2. 加载游戏场景 3. 初始化玩家角色 4. 监听服务器广播消息 5. 开始游戏主循环 6. 处理游戏逻辑和网络消息 ## 📝 使用指南 ### 1. 启动应用 ```typescript import { AppStatusManager } from './App/AppStatus/AppStatusManager'; // 在 Boot 组件中启动 @ccclass('Boot') export class Boot extends Component { start() { // 获取管理器实例 const appManager = AppStatusManager.getInstance(); // 启动应用 appManager.start(); } update(deltaTime: number) { // 在主循环中更新状态机 AppStatusManager.getInstance().update(deltaTime); } } ``` ### 2. 切换状态 ```typescript import { AppStatusManager } from './App/AppStatus/AppStatusManager'; // 从登录状态切换到游戏状态 AppStatusManager.getInstance().changeState('Game', { player: playerInfo, isNewPlayer: false }); // 从游戏状态返回登录状态 AppStatusManager.getInstance().changeState('Login'); ``` ### 3. 获取当前状态 ```typescript // 获取当前状态名称 const stateName = AppStatusManager.getInstance().getCurrentStateName(); console.log(`当前状态: ${stateName}`); // 获取当前状态实例 const currentState = AppStatusManager.getInstance().getCurrentState(); ``` ## 🔄 完整流程示例 ### 启动到游戏的完整流程 ``` 1. Boot 组件启动 ↓ 2. AppStatusManager.start() ↓ 3. 切换到 Boot 状态 ↓ 4. 初始化网络并连接服务器 ↓ 5. 连接成功,切换到 Login 状态 ↓ 6. 加载并显示登录 UI ↓ 7. 用户输入账号并点击登录 ↓ 8. 调用 Login API ↓ 9. 登录成功,切换到 Game 状态 ↓ 10. 加载游戏场景 ↓ 11. 初始化玩家角色 ↓ 12. 监听服务器广播消息 ↓ 13. 开始游戏主循环 ``` ## 📡 网络协议使用 ### Boot 状态 ```typescript // 配置网络 const config: NetConfig = { serverUrl: 'http://localhost:3000', timeout: 30000, autoReconnect: true, reconnectInterval: 3000, maxReconnectTimes: 5 }; ``` ### Login 状态 ```typescript // 由 UILogin 调用登录 API const result = await netManager.callApi('Login', { account: account }); // 登录成功后切换状态 if (result && result.success) { AppStatusManager.getInstance().changeState('Game', { player: result.player, isNewPlayer: result.isNewPlayer }); } ``` ### Game 状态 ```typescript // 监听服务器广播 netManager.listenMsg('PlayerJoin', (msg) => { console.log(`玩家 ${msg.playerName} 加入游戏`); // 在场景中创建其他玩家 }); netManager.listenMsg('PlayerMove', (msg) => { console.log(`玩家 ${msg.playerName} 移动`); // 更新其他玩家位置 }); // 发送 API const result = await netManager.callApi('Move', { x: targetX, y: targetY }); ``` ## ⚠️ 注意事项 1. **状态切换参数**: 切换到 Game 状态时必须传递 player 参数 2. **网络初始化**: Boot 状态必须在网络连接成功后才能切换状态 3. **资源清理**: 切换状态时注意清理前一个状态的资源 4. **消息监听**: Game 状态退出时要取消所有服务器消息监听 5. **异步处理**: 状态的 onEnter 方法是异步的,注意使用 await ## 🔍 调试技巧 ### 状态切换日志 ```typescript // BaseState 会自动输出状态切换日志 // [FSM] Enter state: Boot // [FSM] Exit state: Boot // [FSM] Enter state: Login ``` ### 网络状态日志 ```typescript // NetManager 会输出网络状态日志 // [NetManager] 网络已连接 // [NetManager] 网络已断开 // [NetManager] 正在重连... ``` ### 游戏状态信息 ```typescript // 在 Game 状态中查看玩家信息 const gameState = AppStatusManager.getInstance() .getCurrentState() as AppStatusGame; console.log('玩家信息:', gameState._player); console.log('是否新玩家:', gameState._isNewPlayer); ``` ## 💡 最佳实践 1. **单一入口**: 通过 AppStatusManager 统一管理所有状态切换 2. **参数传递**: 使用 params 在状态间传递必要的数据 3. **资源管理**: 每个状态负责自己的资源加载和释放 4. **错误处理**: 网络错误时提供友好的提示并返回合适的状态 5. **状态独立**: 每个状态保持独立,避免直接依赖其他状态 ## 🎯 扩展状态 ### 添加新状态 ```typescript // 1. 创建新状态类 class AppStatusLobby extends BaseState { constructor(fsm: FSM) { super(fsm, "Lobby"); } onEnter(params?: any): void { super.onEnter(params); console.log("[AppStatusLobby] 进入大厅"); // 显示大厅 UI } onExit(): void { super.onExit(); // 清理大厅资源 } } // 2. 在 AppStatusManager 中注册 private initStates(): void { this._fsm.addState(new AppStatusBoot(this._fsm)); this._fsm.addState(new AppStatusLogin(this._fsm)); this._fsm.addState(new AppStatusLobby(this._fsm)); // 新增 this._fsm.addState(new AppStatusGame(this._fsm)); } // 3. 修改状态流转 // Login -> Lobby -> Game ``` ## 📚 相关文档 - [Framework/FSM README](../../Framework/FSM/README.md) - 状态机框架 - [Framework/Net README](../../Framework/Net/README.md) - 网络通信 - [App/Login README](../Login/README.md) - 登录模块