Files
g0v0-server/MULTIPLAYER_IMPROVEMENTS.md
2025-08-22 13:52:28 +08:00

4.8 KiB
Raw Blame History

多人游戏观战和实时排行榜改进说明

主要改进

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字段用于存储事件详细信息

性能优化建议

  1. 缓冲区大小调整: 根据实际需求调整分数帧缓冲区大小默认50帧
  2. 广播频率调整: 可以根据网络条件调整排行榜广播频率默认1秒
  3. 内存清理: 定期清理过期的游戏状态快照和观战者状态
  4. 连接池优化: 配置Redis连接池以处理高并发请求

故障排除

常见问题

  1. 排行榜不更新: 检查Redis连接和广播任务状态
  2. 观战者状态不同步: 确认SpectatorSyncManager已正确初始化
  3. 分数数据丢失: 检查缓冲区大小和清理逻辑

日志监控

关键日志点:

  • [MultiplayerHub] Synced gameplay state for user X
  • [MultiplayerHub] Broadcasted leaderboard update to room X
  • Error updating score for user X
  • Error in leaderboard broadcast loop

调试模式

在开发环境中启用详细日志:

import logging
logging.getLogger("app.signalr.hub.multiplayer").setLevel(logging.DEBUG)