使用 Node.JS 构建的多人 JavaScript 游戏 - 分隔玩家

Posted

技术标签:

【中文标题】使用 Node.JS 构建的多人 JavaScript 游戏 - 分隔玩家【英文标题】:Multiplayer JavaScript game built with Node.JS - Separating players 【发布时间】:2012-02-20 10:25:54 【问题描述】:

我有一个找不到答案的问题。

我正在尝试使用 Node.JS 和 Socket.IO 构建多人游戏。我已经建立了一个聊天室作为我的第一个实验,因此我可以进行广播等工作。现在我正处于想要使用 Canvas 进行某些工作的地步。

我遇到的问题是让我的头脑围绕着多个独立的玩家。我知道每个玩家都会将他们的 x,y 数据线发送到服务器,服务器会广播这些数据,但是客户端如何知道要显示多少玩家,我猜他们必须存储在某个地方的数组中。

【问题讨论】:

【参考方案1】:

我的实现将非常天真和简化,没有延迟补偿、外推等,但它应该指出节点“多人游戏”的一般概念。

我认为最简单的方法是在客户端和服务器上都有一个包含玩家(实体)的关联数组。然后从客户端发送action: "move", target:[32, 100] 之类的命令,并使用服务器逻辑(运行真实游戏的位置)处理此命令。对于每个套接字on connection,您应该分配一个播放器对象或 id,以便您可以像这样访问它:

var lastPlayerID = 0;
var players = ;

server.on("connection", function(socket) 

  var newcommer = new Player(id: lastPlayerID);      
  players[lastPlayerID] = newcommer;
  socket.player = newcommer; // or lastPlayerID
  lastPlayerID++;      

  socket.onMessage = function(message) 
    this.player.doSomething(); 
  

);

然后假设每个 100 毫秒,您可以向所有连接的玩家发送快照:


  timestamp: game.delta,
  players: 
    1: x: 32, y: 100,
    2: x: 14, y: 11
  

然后在客户端接收数据并从旧值插入到新值。

// duration in this simplified example is snapshot sending interval in [ms]
Player.prototype.interpolateTo = function(data, duration) 
  if(typeof data.x != "undefined") 
    // step needed to get `destination x` within `duration` miliseconds
    this.stepValues.x = Math.abs(data.x - this.x) / duration;
    this.target.x = data.x;
   
  // ...


// step you call for each game loop iteration
Player.prototype.step = function(delta) 
  if(this.x < this.target.x) 
    this.x += delta * this.stepValues.x
  

对于最多包含 20 个对象的半街机游戏来说,这是一个足够的算法。减少快照的间隔使其几乎适合具有更多对象的策略游戏。您的主要敌人是带宽使用,您可以减少带宽使用以最小化数据包的大小。例如阅读 BiSON、LZW 并不要发送自上次快照以来未更改的数据。

我的名声不允许我发布所有链接,所以我将它们附在此处: http://pastebin.com/Kh3wvF1D

Glenn Fiedler 对多人游戏概念的一般介绍:

http://gafferongames.com/networking-for-game-programmers/what-every-programmer-needs-to-know-about-game-networking/

Quake 中的一些多人游戏技巧: 这将为您提供有关插值和外推(预测)的线索

http://fabiensanglard.net/quakeSource/quakeSourcePrediction.php

Valve 关于延迟补偿和一般优化的文章:

https://developer.valvesoftware.com/wiki/Latency_Compensating_Methods_in_Client/Server_In-game_Protocol_Design_and_Optimization

帝国时代的多人游戏技巧:

http://zoo.cs.yale.edu/classes/cs538/readings/papers/terrano_1500arch.pdf#search=%22Real%20time%20strategy%20networking%20lockstep%22

你也可以阅读我关于优化带宽使用的文章

http://rezoner.net/minimizing-bandwidth-usage-in-html5-games-using-websocket,299

+1 对于 Ivo 的 Wetzel Mapple.js,这是一大堆知识。

https://github.com/BonsaiDen/Maple.js

【讨论】:

欢迎来到 ***!很好的答案,继续这样下去,你的缺乏代表不应该是一个很长时间的问题。 :) 谢谢你这么详细的解释:)【参考方案2】:

玩家不会将他们的 x,y 坐标发送到服务器,这将允许通过手动发送坐标来作弊。

每个玩家向服务器发送“左/右/上/下移动”事件。然后服务器更新位置并定期广播所有玩家的位置(或位置的增量)。

然后每个客户端获取所有这些播放器增量并呈现它们。在客户端实现方面,我会有某种 Board/Map 对象,它会有一个 RenderableEntities 列表。然后,我只需使用新位置更新 RenderableEntities 并定期重绘所有实体。

我建议你看看Maple.js

【讨论】:

啊当然。感谢您的解释。因此,逻辑将位于服务器上,并向玩家广播新的位置。我会广播一个数组或对象,然后在客户端循环显示吗?我会看看 Maple.js 谢谢 :) @Henryz 出于效率目的,您只广播已更改位置的对象,并且您只广播位置的实际差异而不是整个位置。数据结构由你决定,元组对象很好 id: [x, y], otherid: [x, y] 恐怕我正试图让 Maple.js 演示运行,但它根本不起作用。在过去 3 年中没有 repo 更新。还有其他可以在客户端和服务器之间实现这种同步更新的建议吗?【参考方案3】:

同步每个玩家的 X 和 Y 坐标的另一种方法是使用Lance。 它是一个开源的 javascript 库,可通过权威服务器处理多个玩家的位置校正。

如果您需要同步坐标以外的其他内容,例如对象名称或头像属性,这将非常有用。或者,如果您的球员有速度。

【讨论】:

以上是关于使用 Node.JS 构建的多人 JavaScript 游戏 - 分隔玩家的主要内容,如果未能解决你的问题,请参考以下文章

Node.js 多人游戏多线程和多核

多人 HTML5、Node.js、Socket.IO

使用Cocos2d-Javascript和Node.js的多人游戏

node.js 中的多人游戏架构 - 与 Redux 的状态管理和同步

使用node.js实现多人聊天室(socket.ioB/S)

TCP 和 Node.js 的实时多人游戏原理