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

Multiplayer JavaScript game built with Node.JS - Separating players

本文关键字:游戏 JavaScript 分离 玩家 Node JS 构建 使用      更新时间:2023-09-26

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

我正在尝试用Node.JS和Socket.IO构建一个多人游戏。我已经建立了一个聊天室作为我的第一个实验,所以我可以使用广播等。现在我正处于想用Canvas做点什么的时候。

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

我的实现将非常天真和简化,没有滞后补偿、外推等,但它应该指出带有节点的"多层"的一般概念。

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

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

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

然后,每个客户端获取所有这些玩家增量并进行渲染。在客户端实现方面,我会有某种Board/Map对象,它会有一个RenderableEntities列表。然后,我只是用新的位置更新RenderableEntities,并定期重新绘制所有实体。

我建议您查看Maple.js

同步X&每个玩家的Y坐标都是使用Lance。这是一个开源JavaScript库,通过权威服务器为多个玩家处理位置校正。

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