# 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<void> {
    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
