4.8 KiB
4.8 KiB
多人游戏观战和实时排行榜改进说明
主要改进
1. 游戏状态缓冲区 (GameplayStateBuffer)
- 实时分数缓冲: 为每个房间的每个玩家维护最多50帧的分数数据
- 实时排行榜: 自动计算和维护实时排行榜数据
- 游戏状态快照: 为新加入的观众创建完整的游戏状态快照
- 观战者状态缓存: 跟踪观战者状态以优化同步
2. 观战同步管理器 (SpectatorSyncManager)
- 跨Hub通信: 通过Redis在MultiplayerHub和SpectatorHub之间同步状态
- 事件通知: 游戏开始/结束、用户状态变化等事件的实时通知
- 异步消息处理: 订阅和处理观战相关事件
3. 增强的MultiplayerHub功能
新增方法:
UpdateScore(client, score_data): 接收实时分数更新GetLeaderboard(client): 获取当前排行榜RequestSpectatorSync(client): 观战者请求状态同步
改进的方法:
JoinRoomWithPassword: 增强新用户加入时的状态同步ChangeState: 添加观战状态处理和分数缓冲区管理start_gameplay: 启动实时排行榜广播和创建游戏快照change_room_state: 处理游戏结束时的清理工作
4. 实时排行榜系统
- 自动广播: 每秒更新一次实时排行榜
- 智能启停: 根据游戏状态自动启动/停止广播任务
- 最终排行榜: 游戏结束时发送最终排行榜
客户端集成示例
JavaScript客户端示例
// 连接到MultiplayerHub
const connection = new signalR.HubConnectionBuilder()
.withUrl("/multiplayer")
.build();
// 监听实时排行榜更新
connection.on("LeaderboardUpdate", (leaderboard) => {
updateLeaderboardUI(leaderboard);
});
// 监听游戏状态同步(观战者)
connection.on("GameplayStateSync", (snapshot) => {
syncSpectatorUI(snapshot);
});
// 监听最终排行榜
connection.on("FinalLeaderboard", (finalLeaderboard) => {
showFinalResults(finalLeaderboard);
});
// 发送分数更新(玩家)
async function updateScore(scoreData) {
try {
await connection.invoke("UpdateScore", scoreData);
} catch (err) {
console.error("Error updating score:", err);
}
}
// 请求观战同步(观战者)
async function requestSpectatorSync() {
try {
await connection.invoke("RequestSpectatorSync");
} catch (err) {
console.error("Error requesting sync:", err);
}
}
// 获取当前排行榜
async function getCurrentLeaderboard() {
try {
return await connection.invoke("GetLeaderboard");
} catch (err) {
console.error("Error getting leaderboard:", err);
return [];
}
}
Python客户端示例
import signalrcore
# 创建连接
connection = signalrcore.HubConnectionBuilder() \
.with_url("ws://localhost:8000/multiplayer") \
.build()
# 监听排行榜更新
def on_leaderboard_update(leaderboard):
print("Leaderboard update:", leaderboard)
# 更新UI显示排行榜
connection.on("LeaderboardUpdate", on_leaderboard_update)
# 监听游戏状态同步
def on_gameplay_state_sync(snapshot):
print("Gameplay state sync:", snapshot)
# 同步观战界面
connection.on("GameplayStateSync", on_gameplay_state_sync)
# 发送分数更新
async def send_score_update(score, combo, accuracy):
await connection.send("UpdateScore", {
"score": score,
"combo": combo,
"accuracy": accuracy,
"completed": False
})
# 启动连接
connection.start()
配置要求
Redis配置
确保Redis服务器运行并配置正确的连接参数:
# 在app/dependencies/database.py中
REDIS_CONFIG = {
'host': 'localhost',
'port': 6379,
'db': 0,
'decode_responses': True
}
数据库表结构
确保multiplayer_event表包含以下字段:
event_detail: JSON字段,用于存储事件详细信息
性能优化建议
- 缓冲区大小调整: 根据实际需求调整分数帧缓冲区大小(默认50帧)
- 广播频率调整: 可以根据网络条件调整排行榜广播频率(默认1秒)
- 内存清理: 定期清理过期的游戏状态快照和观战者状态
- 连接池优化: 配置Redis连接池以处理高并发请求
故障排除
常见问题
- 排行榜不更新: 检查Redis连接和广播任务状态
- 观战者状态不同步: 确认SpectatorSyncManager已正确初始化
- 分数数据丢失: 检查缓冲区大小和清理逻辑
日志监控
关键日志点:
[MultiplayerHub] Synced gameplay state for user X[MultiplayerHub] Broadcasted leaderboard update to room XError updating score for user XError in leaderboard broadcast loop
调试模式
在开发环境中启用详细日志:
import logging
logging.getLogger("app.signalr.hub.multiplayer").setLevel(logging.DEBUG)