# AppStatus 应用状态机使用指南 ## 📚 概述 AppStatus 是基于 FSM 状态机实现的应用级状态管理系统,负责管理整个游戏的状态流转。 **简化后的流程**: Boot(连接) → Login(登录) → Game(游戏世界) ## 🏗️ 项目结构 ``` assets/scripts/ ├── Boot/ │ └── Boot.ts # 启动组件(挂载到场景) ├── App/ │ └── AppStatus/ │ ├── AppStatusBoot.ts # 启动状态(连接服务器) │ ├── AppStatusLogin.ts # 登录状态(调用Login API) │ ├── AppStatusGame.ts # 游戏状态(监听广播) │ └── AppStatusManager.ts # 状态管理器 ├── Framework/ │ ├── FSM/ # 状态机框架 │ └── Net/ # 网络通信框架 └── Shared/ └── protocols/ # TSRPC协议定义 ``` ## 🚀 快速开始 ### 1. 在场景中使用 1. 打开 Cocos Creator 2. 打开主场景 `assets/scenes/main.scene` 3. 创建一个空节点,命名为 "Boot" 4. 将 `assets/scripts/Boot/Boot.ts` 拖拽到 Boot 节点上 5. 运行游戏 ### 2. 状态流转 应用启动后会自动按以下顺序流转: ``` Boot(启动) → Login(登录) → Game(游戏世界) ↑ ↓ ↓ └───────────────────────────┘ (退出/死亡返回登录) ## 📋 各状态详解 ### Boot 启动状态 **触发时机**: 应用启动时 **主要工作**: - 初始化网络管理器 - 连接服务器 **完成后**: 自动切换到 Login 状态 ### Login 登录状态 **触发时机**: Boot 状态完成后 **主要工作**: - 显示登录界面 - 等待用户输入玩家ID - 调用 Login API 登录 **如何触发登录**: ```typescript // 在登录UI中调用 const loginState = AppStatusManager.getInstance() .getCurrentState() as AppStatusLogin; await loginState.login("player123", "玩家昵称"); ``` **协议**: - API: `Login` - 请求: `{ playerId: string, playerName?: string }` - 响应: `{ success: boolean, player: PlayerInfo, isNewPlayer: boolean }` **完成后**: 登录成功后直接进入 Game 状态 ### Game 游戏状态 **触发时机**: 登录成功后 **主要工作**: - 接收登录返回的玩家信息(PlayerInfo) - 加载游戏场景 - 创建玩家角色 - 监听服务器广播消息 - 运行游戏主循环 **监听的服务器广播**: ```typescript // PlayerJoin - 其他玩家加入 NetManager.getInstance().listenMsg("PlayerJoin", (msg) => { console.log(`${msg.playerName} 加入了游戏`); // 在场景中创建其他玩家 }); // PlayerMove - 其他玩家移动 NetManager.getInstance().listenMsg("PlayerMove", (msg) => { console.log(`${msg.playerName} 移动到 (${msg.position.x}, ${msg.position.y})`); // 更新其他玩家位置 }); // Chat - 聊天消息 NetManager.getInstance().listenMsg("Chat", (msg) => { console.log(`${msg.playerName}: ${msg.content}`); // 显示聊天内容 }); ``` **可用操作**: ```typescript const gameState = AppStatusManager.getInstance() .getCurrentState() as AppStatusGame; // 移动(调用Move API) await NetManager.getInstance().callApi("Move", { x: 10, y: 5 }); // 发送聊天(调用Send API) await NetManager.getInstance().callApi("Send", { content: "Hello!" }); // 暂停/恢复游戏 gameState.pauseGame(); gameState.resumeGame(); // 玩家死亡 gameState.onPlayerDeath(); // 退出游戏(返回登录) gameState.quitGame(); ``` ## 🎮 AppStatusManager API ### 获取管理器实例 ```typescript import { AppStatusManager } from './App/AppStatus/AppStatusManager'; const appManager = AppStatusManager.getInstance(); ``` ### 主要方法 #### start() 启动应用,从 Boot 状态开始 ```typescript appManager.start(); ``` #### changeState(stateName, params?) 手动切换状态 ```typescript // 切换到登录状态 appManager.changeState("Login"); // 切换到大厅状态并传递用户信息 appManager.changeState("Lobby", { userInfo: { userId: "123", username: "玩家" } }); // 切换到游戏状态 appManager.changeState("Game", { roomId: "room123", userInfo: currentUser }); ``` #### getCurrentStateName() 获取当前状态名称 ```typescript const stateName = appManager.getCurrentStateName(); console.log(`当前状态: ${stateName}`); // 输出: "Login" ``` #### getCurrentState() 获取当前状态实例 ```typescript const currentState = appManager.getCurrentState(); if (currentState) { console.log(`当前状态: ${currentState.name}`); } ``` #### update(dt) 更新状态机(在游戏主循环中调用) ```typescript // Boot.ts 中已自动处理 update(deltaTime: number) { this._appStatusManager.update(deltaTime); } ``` ## 🔧 扩展新状态 如果需要添加新的应用状态: ### 1. 创建状态类 ```typescript import { BaseState } from "../../Framework/FSM/BaseState"; export class AppStatusNewState extends BaseState { constructor(fsm: any) { super(fsm, "NewState"); } onEnter(params?: any): void { super.onEnter(params); // 进入状态的逻辑 } onExit(): void { super.onExit(); // 退出状态的逻辑 } } ``` ### 2. 在 AppStatusManager 中注册 ```typescript // AppStatusManager.ts import { AppStatusNewState } from "./AppStatusNewState"; private initStates(): void { // ... 其他状态 this._fsm.addState(new AppStatusNewState(this._fsm)); } ``` ### 3. 从其他状态切换 ```typescript this._fsm.changeState("NewState", { /* 参数 */ }); ``` ## 💡 最佳实践 ### 1. 状态间传递数据 使用 `changeState` 的第二个参数传递数据: ```typescript // 传递数据 this._fsm.changeState("Lobby", { userInfo: { userId: "123", username: "玩家" } }); // 接收数据 onEnter(params?: any): void { if (params && params.userInfo) { this._userInfo = params.userInfo; } } ``` ### 2. 保持状态独立 每个状态应该是独立的,不要在状态间共享可变数据,而是通过参数传递。 ### 3. 异步操作处理 在状态的 `onEnter` 中处理异步操作: ```typescript async onEnter(params?: any): Promise { super.onEnter(params); try { await this.loadSomething(); this._fsm.changeState("NextState"); } catch (error) { console.error("加载失败:", error); // 处理错误 } } ``` ### 4. 状态清理 始终在 `onExit` 中清理资源: ```typescript onExit(): void { super.onExit(); // 清理UI // 取消网络监听 // 释放资源 } ``` ## 🐛 调试技巧 ### 1. 查看状态流转日志 所有状态切换都会在控制台输出日志: ``` [FSM] 进入状态: Boot [AppStatusBoot] 开始初始化应用... [FSM] 退出状态: Boot [FSM] 进入状态: Loading ``` ### 2. 查看当前状态 ```typescript console.log("当前状态:", AppStatusManager.getInstance().getCurrentStateName()); ``` ### 3. 直接切换到指定状态(测试用) ```typescript // 跳过登录直接进入大厅 AppStatusManager.getInstance().changeState("Lobby", { userInfo: { userId: "test", username: "测试用户" } }); ``` ## 📝 TODO 清单 当前 AppStatus 模块已完成基础框架,但以下功能需要后续实现: - [ ] 集成 UI 管理器 - [ ] 实现实际的服务器连接 - [ ] 实现资源预加载 - [ ] 实现房间系统 - [ ] 实现匹配系统 - [ ] 实现游戏场景加载 - [ ] 添加状态转换动画 - [ ] 添加错误处理和重试机制 ## 🎯 下一步 1. 实现 UI 系统 2. 创建登录界面 3. 连接服务器 4. 实现房间和匹配功能 5. 开发游戏主逻辑 --- 更新时间: 2025-12-14