【问题标题】:Node.js game logicsNode.js 游戏逻辑
【发布时间】:2012-06-01 11:28:49
【问题描述】:

我正在制作实时多人赛车游戏。现在我需要帮助在 Node.js TCP(网络)服务器中编写游戏逻辑。我不知道这是否可能,我不知道我这样做是否正确,但我正在尽力而为。我知道很难理解我蹩脚的英语,所以我做了这幅“画”:)
感谢您的宝贵时间

【问题讨论】:

    标签: node.js mmo


    【解决方案1】:

    要详细说明 driushkin 的答案,您应该使用远程过程调用 (RPC) 和事件队列。这就像您发布的图像一样,其中每个数据包代表一个“命令”或带有一些参数(即运动方向)的 RPC。您还需要一个事件队列来确保 RPC 按时按顺序执行。这将需要每个要执行的命令的时间戳或帧数(在未来的某个时间点,以简单的方案),并同步手表(二战风格)。

    您可能会注意到此方案中的一个关键弱点:由于网络延迟、恶意用户等原因,RPC 消息可能会延迟(在应该应用它们的时间之后到达)。在一个简单的方案中,延迟的 RPC 会被丢弃。这很好,因为所有客户端(甚至是发起者!)在行动之前都等待服务器发送 RPC(如果发起客户端没有等待服务器消息,他的游戏状态将与服务器不同步,并且您的游戏会被破坏)。

    考虑滞后对此类方案的影响。假设客户端 A 到服务器的延迟是 100 毫秒,而回程也是 100 毫秒。这意味着客户端输入如下:

    • 客户端A按键,发送RPC到服务器,本地没有添加(0ms)
    • 服务器接收并重新广播 RPC (100ms)
    • 客户端 A 收到自己的事件,现在终于将其添加到自己的事件队列中进行处理(200 毫秒)

    如您所见,客户端在按键后 1/5 秒内对自己的事件做出反应。这是相当不错的 100 毫秒延迟。单程跨洋延迟很容易超过 200 毫秒,拨号连接(很少见,但今天仍然存在)可能会出现 > 500 毫秒的延迟峰值。如果您在 LAN 或类似的地方玩游戏,这些都无关紧要,但在互联网上,这种反应迟钝可能令人难以忍受。

    这就是客户端预测 (CSP) 概念的用武之地。CSP 被认为是庞大而可怕的,但正确且经过深思熟虑地实施它实际上非常简单。 CSP 的有趣特性是客户端可以立即处理他们的输入(客户端预测会发生什么)。当然,客户可能(而且经常会)是错误的。这意味着客户端将需要一种从服务器应用更正的方法。这意味着您需要一种方法让服务器验证、拒绝或修改来自客户端的 RPC 请求,以及一种序列化游戏状态的方法(以便可以将其恢复为重新模拟的基点)。

    有很多关于这样做的好资源。我特别喜欢http://www.gabrielgambetta.com/?p=22,但你真的应该寻找一本好的多人游戏编程书籍。


    我还必须推荐 socket.io,即使在阅读了有关 Flex 和 AS3 的 cmets 之后也是如此。易用性(以及与节点的简单集成)使其成为我曾经使用过的通过 HTTP 进行网络游戏的最佳(最佳?)选项之一。我会做任何必要的调整才能使用它。我相信 AIR/AS3 至少有一个 WebSockets 库,即使 socket.io 本身不可用。

    【讨论】:

    • 所以你的意思是如果我会使用 WebSockets 那么我不应该担心 ping 和其他东西?
    • 不,我的意思是您应该使用 WebSockets CSP,这样您就不必担心太多延迟问题。跨度>
    【解决方案2】:

    这听起来像是socket.io 非常适合。它是一个库,可为您在浏览器和服务器上提供实时可能性。

    【讨论】:

    • 它是 Flash 客户端。我猜它不支持socket.io。
    • 对于带有 socket.io 的 Flash 客户端,您应该查看 FalshSocket.IO
    • 我看到它只支持 Flex 应用程序。我的客户是纯 AS3。
    【解决方案3】:

    您可以在commands 中对events 建模:客户端向服务器发送命令move,然后服务器验证此命令,如果一切正常,他发布事件is moving

    在您的情况下,可能不需要对 P1(好的,您可以移动)和其余的(P1 正在移动)做出不同的响应,后者在这两种情况下都足够了。 is moving 事件应包含所有必要的信息(如当前位置、速度等)。

    在这种最简单的形式中,发出命令会经历一些延迟,直到来自服务器的事件到达,为了避免您可以立即开始移动,然后在事件到达时在必要时应用一些补偿动作。但这可能会变得复杂。

    【讨论】:

    • 我理解正确吗?我像这样“PLAYER|ACTION|POSITION”向服务器发送命令。假设客户端发送命令“P1|START_MOVING|100,0”,当所有客户端收到此命令时,他们会看到 P1 移动。客户端再次发送命令“P1|STOP_MOVING|200,0”(释放移动键后)。如果其他客户端看到 P1 位置错误(如 150,0),则 STOP_MOVING 命令将其位置修复为 200,0
    • @Gugis 是的,差不多。虽然我想强调命令和事件之间的区别:命令告诉服务器做某事,而事件是实际发生的事情。有这种区别可以避免很多混乱。
    猜你喜欢
    • 1970-01-01
    • 2011-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-10
    • 2013-07-31
    • 2018-09-13
    • 1970-01-01
    相关资源
    最近更新 更多