用节点构建的多玩家JavaScript游戏。JS -分离的球员

时间:2023-01-28 18:57:43

I have a question which I cannot find an answer to.

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

I'm experimenting with building a multiplayer game with Node.JS and Socket.IO. I have built a chat room as my first experiment, so I have broadcasts working etc. Now I'm at the point where I want to get something working with Canvas.

我正在尝试用Node构建一个多人游戏。JS和socket . io。我已经建立了一个聊天室作为我的第一个实验,所以我有广播工作等等。现在我想要得到一些与画布有关的东西。

The problem I'm having is getting my head around multiple and independent players. I know that each player will send their x,y cords to the server and the server will broadcast those, but how does the client know how many players to display, I'm guessing they have to be stored in an array somewhere.

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

3 个解决方案

#1


39  

My implementation will be very naive and simplified, no lag compensation, extrapolation and such, but it should point out a general conception of "multiplayering" with node.

我的实现将非常简单和简化,没有滞后补偿、外推等,但它应该指出一个与节点“多进程”的一般概念。

I think the simplest approach is to have an associative array containing players(entities) on both client and server. Then from client side you send commands like {action: "move", target:[32, 100]} and process this command with server logic (where the real game is running). To each socket on connection you should assign a player object or id so you can access it like:

我认为最简单的方法是在客户机和服务器上都有一个包含参与者(实体)的关联数组。然后从客户端发送诸如{action: "move"、target:[32,100]}等命令,并使用服务器逻辑(真正的游戏正在运行的地方)处理此命令。对于连接上的每个套接字,您应该分配一个播放器对象或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(); 
  }

});

Then each let's say 100ms you could send snapshots to all connected players:

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

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

And then at client side receive data and interpolate from old to new values.

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

// 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
  }
}

This is a sufficient algorithm for a semi-arcade game with 20 objects at maximum. Decreasing snapshot's interval makes it almost suitable for strategy game with more objects. Your main enemy is bandwidth usage which you can decrease minimizing packet's size. For instance read about BiSON, LZW and don't send data which haven't changed since last snapshot.

这对于一个最多有20个对象的半拱廊游戏来说是一个足够的算法。减少快照的间隔使得它几乎适用于具有更多对象的策略游戏。你的主要敌人是带宽使用,你可以减少最小的数据包大小。例如,阅读关于BiSON、LZW和不要发送自上次快照以来没有更改的数据。

My reputation doesn't allow me to post all the links, so I have attached them here: http://pastebin.com/Kh3wvF1D

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

General introduction to multiplayer conceptions by Glenn Fiedler:

格伦·菲德勒对多人游戏概念的概述:

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

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

Some multiplayer techniques from Quake: This will give u a clue about interpolation and extrapolation(prediction)

来自Quake的一些多人游戏技术:这将为您提供插值和推断(预测)的线索

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

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

Valve's article about latency compensation and general optimisations:

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

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

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

Multiplayer techniques in Age of Empires:

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

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

http://zoo.cs.yale.edu/classes/cs538/readings/papers/terrano_1500arch.pdf搜索= % 22真正% 20时间% 20策略% 20网络% 20因循守旧% 22

You can also read my article about optimizing bandwidth usage

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

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

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

+1 for Ivo's Wetzel Mapple.js it's a big pile of knowledge.

+1表示Ivo的Wetzel Mapple。这是一大堆知识。

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

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

#2


10  

Players don't send their x,y co-ordinates to the server, that would allow for cheating by manually sending the co-ordinates.

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

Each player sends "moving left/right/up/down" events to the server. The server then updates positions and periodically broadcasts the position (or the deltas in position) of all the players.

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

Each client then takes all these player deltas and renders them. In terms of client side implementation I would have some kind of Board/Map object and it would have a list of RenderableEntities. I then just update the RenderableEntities with new positions and periodically redraw all the entities.

然后每个客户端获取所有的玩家增量并呈现它们。就客户端实现而言,我将有某种Board/Map对象,它将有一个RenderableEntities列表。然后我用新的位置更新RenderableEntities,并定期重新绘制所有实体。

I recommend you take a look at Maple.js

我建议你看看mapley .js

#3


1  

Another way to synchronize the X & Y coordinates of each player is to use the Lance. It is an open-source JavaScript library that handles position correction for multiple players with an authoritative server.

另一种同步每个玩家的X和Y坐标的方法是使用长矛。它是一个开放源码的JavaScript库,可以处理具有权威服务器的多个播放器的位置修正。

It will be useful if you need to synchronize other things besides the coordinates, like the object name or the avatar properties. Or if your players have velocities.

如果您需要同步坐标之外的其他东西,比如对象名或avatar属性,这将非常有用。或者如果你的球员有速度。

#1


39  

My implementation will be very naive and simplified, no lag compensation, extrapolation and such, but it should point out a general conception of "multiplayering" with node.

我的实现将非常简单和简化,没有滞后补偿、外推等,但它应该指出一个与节点“多进程”的一般概念。

I think the simplest approach is to have an associative array containing players(entities) on both client and server. Then from client side you send commands like {action: "move", target:[32, 100]} and process this command with server logic (where the real game is running). To each socket on connection you should assign a player object or id so you can access it like:

我认为最简单的方法是在客户机和服务器上都有一个包含参与者(实体)的关联数组。然后从客户端发送诸如{action: "move"、target:[32,100]}等命令,并使用服务器逻辑(真正的游戏正在运行的地方)处理此命令。对于连接上的每个套接字,您应该分配一个播放器对象或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(); 
  }

});

Then each let's say 100ms you could send snapshots to all connected players:

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

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

And then at client side receive data and interpolate from old to new values.

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

// 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
  }
}

This is a sufficient algorithm for a semi-arcade game with 20 objects at maximum. Decreasing snapshot's interval makes it almost suitable for strategy game with more objects. Your main enemy is bandwidth usage which you can decrease minimizing packet's size. For instance read about BiSON, LZW and don't send data which haven't changed since last snapshot.

这对于一个最多有20个对象的半拱廊游戏来说是一个足够的算法。减少快照的间隔使得它几乎适用于具有更多对象的策略游戏。你的主要敌人是带宽使用,你可以减少最小的数据包大小。例如,阅读关于BiSON、LZW和不要发送自上次快照以来没有更改的数据。

My reputation doesn't allow me to post all the links, so I have attached them here: http://pastebin.com/Kh3wvF1D

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

General introduction to multiplayer conceptions by Glenn Fiedler:

格伦·菲德勒对多人游戏概念的概述:

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

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

Some multiplayer techniques from Quake: This will give u a clue about interpolation and extrapolation(prediction)

来自Quake的一些多人游戏技术:这将为您提供插值和推断(预测)的线索

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

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

Valve's article about latency compensation and general optimisations:

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

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

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

Multiplayer techniques in Age of Empires:

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

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

http://zoo.cs.yale.edu/classes/cs538/readings/papers/terrano_1500arch.pdf搜索= % 22真正% 20时间% 20策略% 20网络% 20因循守旧% 22

You can also read my article about optimizing bandwidth usage

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

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

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

+1 for Ivo's Wetzel Mapple.js it's a big pile of knowledge.

+1表示Ivo的Wetzel Mapple。这是一大堆知识。

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

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

#2


10  

Players don't send their x,y co-ordinates to the server, that would allow for cheating by manually sending the co-ordinates.

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

Each player sends "moving left/right/up/down" events to the server. The server then updates positions and periodically broadcasts the position (or the deltas in position) of all the players.

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

Each client then takes all these player deltas and renders them. In terms of client side implementation I would have some kind of Board/Map object and it would have a list of RenderableEntities. I then just update the RenderableEntities with new positions and periodically redraw all the entities.

然后每个客户端获取所有的玩家增量并呈现它们。就客户端实现而言,我将有某种Board/Map对象,它将有一个RenderableEntities列表。然后我用新的位置更新RenderableEntities,并定期重新绘制所有实体。

I recommend you take a look at Maple.js

我建议你看看mapley .js

#3


1  

Another way to synchronize the X & Y coordinates of each player is to use the Lance. It is an open-source JavaScript library that handles position correction for multiple players with an authoritative server.

另一种同步每个玩家的X和Y坐标的方法是使用长矛。它是一个开放源码的JavaScript库,可以处理具有权威服务器的多个播放器的位置修正。

It will be useful if you need to synchronize other things besides the coordinates, like the object name or the avatar properties. Or if your players have velocities.

如果您需要同步坐标之外的其他东西,比如对象名或avatar属性,这将非常有用。或者如果你的球员有速度。