mirror of
https://github.com/ChuXunYu/OnlineRpg.git
synced 2026-01-31 08:31:26 +00:00
2
This commit is contained in:
290
战斗系统修复说明.md
Normal file
290
战斗系统修复说明.md
Normal file
@@ -0,0 +1,290 @@
|
||||
# 战斗系统输入处理修复
|
||||
|
||||
## 🐛 问题描述
|
||||
|
||||
### 症状1:战斗中输入被错误处理
|
||||
```
|
||||
>>> 你的回合 <<<
|
||||
【战斗】> attack
|
||||
无效选项。请输入1-5。 ❌ 错误:被大厅菜单处理器处理
|
||||
```
|
||||
|
||||
### 症状2:不断显示战斗菜单
|
||||
```
|
||||
【战斗】> 1
|
||||
================================
|
||||
战斗中
|
||||
================================
|
||||
等待你的回合...
|
||||
================================
|
||||
【战斗】> 2
|
||||
================================
|
||||
战斗中
|
||||
================================
|
||||
等待你的回合...
|
||||
```
|
||||
|
||||
### 症状3:连接崩溃
|
||||
```
|
||||
terminate called without an active exception
|
||||
Aborted
|
||||
```
|
||||
|
||||
## 🔍 根本原因
|
||||
|
||||
### 主循环逻辑问题
|
||||
|
||||
**修复前的代码**:
|
||||
```cpp
|
||||
while (m_isRunning && m_isConnected) {
|
||||
if (!m_isAuthenticated) {
|
||||
showMainMenu();
|
||||
} else if (m_inBattle) {
|
||||
showBattleMenu(); // ❌ 不管是否轮到玩家都调用
|
||||
} else {
|
||||
showLobbyMenu();
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
}
|
||||
```
|
||||
|
||||
**问题分析**:
|
||||
1. 当 `m_inBattle = true` 但 `m_waitingForTurn = false` 时
|
||||
2. `showBattleMenu()` 被调用 → 等待输入
|
||||
3. 用户输入后,`handleBattleInput()` 检查 `!m_waitingForTurn` 直接返回
|
||||
4. 循环继续,100ms 后再次调用 `showBattleMenu()`
|
||||
5. **无限显示菜单**
|
||||
|
||||
### 状态机混乱
|
||||
|
||||
战斗有三个状态:
|
||||
- 未认证 → 显示主菜单
|
||||
- 在大厅 → 显示大厅菜单
|
||||
- 在战斗中
|
||||
- **轮到玩家** → 显示战斗菜单,接受输入
|
||||
- **不是玩家回合** → 静默等待,不显示菜单
|
||||
|
||||
原来的代码只区分了前两个状态,导致第三个状态处理错误。
|
||||
|
||||
## ✅ 修复方案
|
||||
|
||||
### 1. 改进主循环逻辑
|
||||
|
||||
```cpp
|
||||
void GameClient::run() {
|
||||
if (!connect()) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (m_isRunning && m_isConnected) {
|
||||
if (!m_isAuthenticated) {
|
||||
showMainMenu();
|
||||
} else if (m_inBattle && m_waitingForTurn) {
|
||||
// ✓ 只在战斗中且轮到玩家时才显示战斗菜单
|
||||
showBattleMenu();
|
||||
} else if (!m_inBattle) {
|
||||
// ✓ 不在战斗中,显示大厅菜单
|
||||
showLobbyMenu();
|
||||
} else {
|
||||
// ✓ 在战斗中但不是玩家回合,静默等待
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**关键改进**:
|
||||
- 添加 `m_waitingForTurn` 检查
|
||||
- 只在 `m_inBattle && m_waitingForTurn` 时显示战斗菜单
|
||||
- 不是玩家回合时进入等待状态,不显示任何菜单
|
||||
|
||||
### 2. 简化战斗菜单
|
||||
|
||||
```cpp
|
||||
void GameClient::showBattleMenu() {
|
||||
printTitle("战斗中");
|
||||
std::cout << "输入 'attack' 或 '攻击' 使用普通攻击" << std::endl;
|
||||
printSeparator();
|
||||
|
||||
std::string input;
|
||||
showPrompt();
|
||||
std::getline(std::cin, input);
|
||||
handleBattleInput(input);
|
||||
}
|
||||
```
|
||||
|
||||
**移除了不必要的检查**,因为主循环已经保证只在正确时机调用。
|
||||
|
||||
### 3. 改进输入处理
|
||||
|
||||
```cpp
|
||||
void GameClient::handleBattleInput(const std::string& input) {
|
||||
if (input.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (input == "attack" || input == "攻击") {
|
||||
std::string msg = Protocol::buildMessage(Protocol::C2S_BATTLE_ACTION, {"0", "opponent"});
|
||||
sendMessage(msg);
|
||||
m_waitingForTurn = false; // 行动后设置为 false
|
||||
} else {
|
||||
std::cout << "无效命令。请输入 'attack' 或 '攻击'" << std::endl;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**关键点**:
|
||||
- 执行攻击后设置 `m_waitingForTurn = false`
|
||||
- 添加友好的错误提示
|
||||
|
||||
## 📊 状态转换流程
|
||||
|
||||
### 正确的战斗流程
|
||||
|
||||
```
|
||||
1. 玩家A邀请玩家B
|
||||
↓
|
||||
2. 玩家B接受邀请
|
||||
↓
|
||||
3. 服务器发送 S2C_BATTLE_START
|
||||
→ m_inBattle = true
|
||||
↓
|
||||
4. 服务器发送 S2C_BATTLE_TURN (YOUR_TURN)
|
||||
→ m_waitingForTurn = true
|
||||
↓
|
||||
5. 主循环检测到 (m_inBattle && m_waitingForTurn)
|
||||
→ 调用 showBattleMenu()
|
||||
↓
|
||||
6. 玩家输入 "attack"
|
||||
→ handleBattleInput() 处理
|
||||
→ 发送 C2S_BATTLE_ACTION
|
||||
→ m_waitingForTurn = false
|
||||
↓
|
||||
7. 主循环检测到 (m_inBattle && !m_waitingForTurn)
|
||||
→ 进入等待状态(不显示菜单)
|
||||
↓
|
||||
8. 服务器处理回合,发送战斗日志
|
||||
→ 显示战斗结果
|
||||
↓
|
||||
9. 服务器发送 S2C_BATTLE_TURN (OPP_TURN)
|
||||
→ 保持 m_waitingForTurn = false
|
||||
→ 继续等待
|
||||
↓
|
||||
10. 对手行动完毕,服务器发送 S2C_BATTLE_TURN (YOUR_TURN)
|
||||
→ m_waitingForTurn = true
|
||||
→ 回到步骤 5
|
||||
```
|
||||
|
||||
## 🧪 测试步骤
|
||||
|
||||
### 步骤1:重启客户端
|
||||
```bash
|
||||
cd /mnt/e/50425/Documents/Github/OnlineRpg
|
||||
./build/bin/client
|
||||
```
|
||||
|
||||
### 步骤2:登录两个玩家
|
||||
- 终端1:玩家A登录
|
||||
- 终端2:玩家B登录
|
||||
|
||||
### 步骤3:发起战斗邀请
|
||||
**玩家A**:
|
||||
```
|
||||
【玩家A】> 3
|
||||
目标玩家用户名:玩家B用户名
|
||||
```
|
||||
|
||||
**玩家B**:
|
||||
```
|
||||
*** 玩家A 邀请你战斗!***
|
||||
输入 'accept 玩家A' 接受,或 'reject 玩家A' 拒绝
|
||||
【玩家B】> accept 玩家A
|
||||
```
|
||||
|
||||
### 步骤4:战斗测试
|
||||
|
||||
**预期行为**:
|
||||
```
|
||||
*** 战斗开始!***
|
||||
对手:玩家B(Mage)
|
||||
====================
|
||||
|
||||
>>> 你的回合 <<<
|
||||
输入 'attack' 使用普通攻击
|
||||
================================
|
||||
战斗中
|
||||
================================
|
||||
输入 'attack' 或 '攻击' 使用普通攻击
|
||||
================================
|
||||
【战斗】> attack ← 输入攻击命令
|
||||
【战斗】玩家A HP:150 ← 显示战斗日志
|
||||
【战斗】玩家A 使用 NormalAttack 攻击 玩家B,造成 15 点伤害!
|
||||
← 自动进入等待状态,不显示菜单
|
||||
>>> 对手的回合...
|
||||
【战斗】玩家B HP:85
|
||||
【战斗】玩家B 使用 Fireball 攻击 玩家A,造成 28 点伤害!
|
||||
|
||||
>>> 你的回合 <<< ← 再次轮到玩家
|
||||
================================
|
||||
战斗中
|
||||
================================
|
||||
输入 'attack' 或 '攻击' 使用普通攻击
|
||||
================================
|
||||
【战斗】> attack
|
||||
```
|
||||
|
||||
**成功标志**:
|
||||
- ✅ 输入 `attack` 后正确执行攻击
|
||||
- ✅ 不是自己回合时不显示菜单
|
||||
- ✅ 没有"无效选项。请输入1-5。"错误
|
||||
- ✅ 战斗日志正常显示
|
||||
- ✅ 连接保持稳定,不崩溃
|
||||
|
||||
## 🔧 相关文件
|
||||
|
||||
- `src/client/GameClient.cpp` - 主要修复文件
|
||||
- `src/client/GameClient.h` - 状态变量定义
|
||||
- `include/common/Protocol.h` - 协议定义
|
||||
|
||||
## 📈 后续优化建议
|
||||
|
||||
1. **添加更多技能选择**
|
||||
```
|
||||
【战斗】> skill
|
||||
可用技能:
|
||||
0. 普通攻击
|
||||
1. 强力打击 (消耗10MP)
|
||||
2. 防御姿态 (消耗5MP)
|
||||
选择技能编号:
|
||||
```
|
||||
|
||||
2. **显示双方状态**
|
||||
```
|
||||
你:玩家A (Warrior) HP:122/150 MP:15/20
|
||||
对手:玩家B (Mage) HP:85/100 MP:10/50
|
||||
```
|
||||
|
||||
3. **战斗历史查看**
|
||||
```
|
||||
【战斗】> history
|
||||
第1回合:玩家A 使用 普通攻击 造成 15 伤害
|
||||
第2回合:玩家B 使用 火球术 造成 28 伤害
|
||||
第3回合:玩家A 使用 强力打击 造成 30 伤害
|
||||
```
|
||||
|
||||
4. **逃跑选项**
|
||||
```
|
||||
【战斗】> flee
|
||||
你逃离了战斗!
|
||||
```
|
||||
|
||||
## ✨ 总结
|
||||
|
||||
修复了战斗系统的输入处理逻辑,通过改进主循环状态判断,确保:
|
||||
- 战斗菜单只在正确时机显示
|
||||
- 输入被正确的处理器处理
|
||||
- 不是玩家回合时静默等待
|
||||
- 避免了菜单无限显示和连接崩溃问题
|
||||
|
||||
现在战斗系统应该能够正常工作了!
|
||||
Reference in New Issue
Block a user