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

时间:2012-01-27 12:19:47

标签: javascript node.js canvas socket.io

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

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

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

3 个答案:

答案 0 :(得分:39)

我的实现将非常幼稚和简化,没有滞后补偿,推断等等,但它应该指出节点“多人游戏”的一般概念。

我认为最简单的方法是在客户端和服务器上都有一个包含播放器(实体)的关联数组。然后从客户端发送{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

答案 1 :(得分:11)

玩家不会将x,y坐标发送到服务器,这样可以通过手动发送坐标来进行作弊。

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

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

我建议你看一下Maple.js

答案 2 :(得分:1)

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

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