下面是针对《三国志战略版》风格 SLG 游戏中塔防战斗玩法的「客户端消息分发与状态同步模块」的详细设计。该模块负责:
- 接收服务端推送的战斗状态更新(如怪物出现、塔攻击、技能释放等)
- 派发给具体的子系统(渲染层 / 动作层 / 音效层)
- 保证本地战斗状态与服务端同步、并能在断线后恢复
一、整体模块职责
[网络模块]
│
▼
[消息解包器(MsgDecoder)]
│
▼
[消息分发器(Dispatcher)] ←——— 游戏主循环拉消息
│
┌───┼────────────────────────────┐
│ │ │
▼ ▼ ▼
[战斗场景控制器] [状态同步模块] [战斗UI表现模块]
│ └→ 怪物生成 └→ 塔状态更新 └→ 血量/能量条更新
│ 攻击动画触发 技能冷却同步 计时器/倒计时展示
二、模块结构说明
1. 网络模块
- 支持 TCP/WebSocket 的长连接
- 支持断线重连、自动重发
- 接收到数据后,将
[]byte 包传入 MsgDecoder
1
2
3
4
5
|
// 示例伪代码
function onNetworkReceive(buffer: Uint8Array) {
const message = MsgDecoder.decode(buffer);
Dispatcher.dispatch(message);
}
|
2. 消息解包器 MsgDecoder
- 负责将 Protobuf 字节流解析成结构化对象
- 根据消息 ID 解析为对应类型的结构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
class MsgDecoder {
static decode(buffer: Uint8Array): TowerMessage {
const raw = TowerDefendMessage.decode(buffer);
const cmd = raw.cmd;
const payload = raw.payload;
switch (cmd) {
case CmdType.SYNC_EVENT:
return TowerSyncEvent.decode(payload);
case CmdType.BATTLE_RESULT:
return TowerBattleResult.decode(payload);
...
}
}
}
|
3. 消息分发器 Dispatcher
- 根据消息类型调用相应的模块处理
- 维护一个消息队列,支持在主线程帧循环中逐帧执行(避免卡顿)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
class Dispatcher {
private static queue: TowerMessage[] = [];
static dispatch(msg: TowerMessage) {
queue.push(msg);
}
// 每帧调用
static update() {
while (queue.length > 0) {
const msg = queue.shift();
if (msg instanceof TowerSyncEvent) {
SyncProcessor.processEvent(msg);
} else if (msg instanceof TowerBattleResult) {
BattleResultView.show(msg);
}
}
}
}
|
4. 状态同步模块 SyncProcessor
该模块对接服务端推送的事件列表,负责驱动场景内对象更新。
支持的事件类型例如:
| 事件类型 |
含义说明 |
| MONSTER_SPAWN |
某波怪物开始生成 |
| TOWER_ATTACK |
某塔开始攻击某怪物 |
| MONSTER_HIT |
某怪物受到伤害 |
| TOWER_UPGRADE_DONE |
塔升级完成 |
| SKILL_CAST |
释放了某个技能 |
| MONSTER_DEAD |
怪物死亡 |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
class SyncProcessor {
static processEvent(event: TowerSyncEvent) {
switch (event.eventType) {
case EventType.MONSTER_SPAWN:
MonsterManager.spawn(event.payload);
break;
case EventType.TOWER_ATTACK:
TowerManager.attack(event.payload);
break;
case EventType.MONSTER_HIT:
MonsterManager.applyDamage(event.payload);
break;
...
}
}
}
|
5. 战斗状态模块(模型层)
战斗对象数据结构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
class Monster {
id: number;
hp: number;
position: Vector2;
moveSpeed: number;
// ...
}
class Tower {
id: number;
type: number;
position: Vector2;
level: number;
cooldown: number;
}
|
状态更新周期
- 每帧根据服务端广播事件更新本地状态
- 动画效果由状态差驱动(如:HP 变化 → 播放受击)
6. 战斗 UI 表现模块
- 监听模型层数据更新(或由
SyncProcessor 通知)
- 更新血条、CD 图标、技能按钮状态等
1
2
3
4
5
6
7
8
9
|
class BattleUI {
static onMonsterDamaged(monsterId, newHp) {
// 查找UI控件并更新血量条
}
static onTowerUpgradeDone(towerId) {
// 播放升级成功动画
}
}
|
三、断线重连与状态补偿支持
设计思路
- 所有状态以「事件流」形式广播(时间戳+事件序列)
- 客户端断线时记录
last_seq_id
- 重连后请求补发未收到的事件片段
客户端实现关键点
1
2
3
4
5
6
7
8
9
10
11
|
onReconnect() {
Net.send('ReconnectBattle', {
battleId: currentBattleId,
lastSeqId: this.lastReceivedSeqId
});
}
onReceiveSyncEvent(event) {
this.lastReceivedSeqId = event.seqId;
SyncProcessor.processEvent(event);
}
|
总结:客户端状态同步模块优势
| 特性 |
说明 |
| 解耦 |
网络、解包、状态处理、UI 展示解耦 |
| 保证一致性 |
所有状态由服务端事件广播推送 |
| 可恢复 |
支持断线重连与丢包重发 |
| 可扩展 |
新增事件类型只需加一个 case 逻辑 |
| 支持本地预测(可选) |
可根据技能释放等提前预判表现,提升体验 |