【问题标题】:Timing for multiplayer games in Node.jsNode.js 中多人游戏的时机
【发布时间】:2020-05-25 11:39:15
【问题描述】:

我想用 Node.js 和 socket.io 创建一个简单的多人游戏。我当前的时序设置不是最佳的,因为渲染不流畅。到目前为止,玩家只是在画布上移动的圆圈。

我尝试通过添加一些代码 sn-ps 来大致解释此设置,请在需要更多代码时告诉我。

每次客户端连接到服务器时,都会创建一个新玩家并将其添加到玩家列表中。此外,我们为客户端的关键输入添加了侦听器(这基本上改变了方向)。

io.on("connection", (socket) => {
    const p = playerList.add(socket.id);
    socket.on("keydown", (key) => p.addControlKeyDown(key));
    socket.on("keyup", (key) => p.addControlKeyUp(key));
}

在服务器端,我们有一个更新循环。由于 Node.js 中没有requestAnimationFrame,我尝试使用setInterval。每次更新后,我们都会向所有客户端发送与绘图相关的内容(这就是 p.extract() 的用途)。

function updateLoop() {
    for (p of playerList.players) {
        p.update();
    }
    const currentPlayers = playerList.players.map((p) => p.extract());
    io.emit("playerUpdate", currentPlayers);
}

const interval = setInterval(updateLoop, 30);

我已经玩过这里的 30 毫秒,但它并没有解决问题。

在客户端,我们监听更新:

let players = [];

socket.on("playerUpdate", (currentPlayers) => {
    players = currentPlayers;
});

在客户端我们也有使用requestAnimationFrame的draw loop:

function drawLoop() {
    clearCanvas();
    players.forEach(drawPlayer);
    requestAnimationFrame(drawLoop);
}

服务器和客户端之间的通信是有效的,但是正如你所看到的,时间并不是最佳的。

如何改进?

我的第一个想法是避免客户端循环,因为我们已经在服务器上,并直接从那里向客户端发送绘图请求,但结果更糟。

我知道,对于复杂的多人游戏,必须在同步方面付出更多努力,而且还需要拍摄游戏世界的快照并将“过去”实际呈现给客户。我希望这个简单的例子不需要这么复杂的方法。

【问题讨论】:

  • 似乎只有在服务器返回响应时才能为框架呈现更新,对吧?如果是这样,这绝对是一个错误的想法。您的 FPS 将完全取决于网络质量,这在大多数情况下都不是很好,因此您会“冻结”。
  • 我不确定你的意思。绘图循环甚至在没有发送新更新时也可以工作,因为客户端中有全局“玩家”变量。但你是对的,这可能会导致冻结。这可以通过线性插值和“向前看”来解决。但是这个问题不是在gif中可以看到的吧?编辑:好的,也许正是这个!我在考虑更长的冻结时间。
  • 恕我直言,你应该看看这个方向来解决这个问题 - gamedev.stackexchange.com/questions/5053/…
  • 谢谢。有多个答案。你的意思是马丁的帖子链接在那里吗? stackoverflow.com/questions/3276821/…(“在真正的游戏中你应该做的是在本地位置和远程位置之间进行插值。”)。听起来很有趣!
  • 您的问题似乎格式正确,所以我投了赞成票。好像位置插值有帮助,那我写个答案吧?

标签: node.js socket.io html5-canvas multiplayer requestanimationframe


【解决方案1】:

第一个问题是您在客户端的渲染与来自服务器的响应相耦合。换句话说,很大程度上取决于您网络的 QoS,这在大多数情况下并不是很好。你会得到那些“冻结”。

您可以通过对玩家的位置引入插值来消除这种情况(您在 cmets 中是对的)。

粗略地说,您需要“猜测”其他玩家会去哪里,直到响应到达客户端。

有很好的解释here

从客户端的角度来看,这种方法和以前一样顺利 - 客户端预测独立于更新延迟工作,因此它显然也适用于可预测的,如果相对不频繁的状态更新。但是,由于游戏状态以低频率广播(继续示例,每 100 毫秒),客户端拥有关于可能在世界各地移动的其他实体的非常少的信息。

因此,我建议您通读上述文章。我很高兴地添加了一些我们在 cmets 中所做的参考:

这是一个巨大的话题,已经回答了问题,所以最好给你一个你需要寻找的方向,而不是再次解释它。希望对你有帮助。

【讨论】:

    猜你喜欢
    • 2013-05-22
    • 2012-07-09
    • 2012-07-11
    • 1970-01-01
    • 1970-01-01
    • 2013-05-22
    • 1970-01-01
    • 2011-07-16
    • 1970-01-01
    相关资源
    最近更新 更多