使用 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 游戏 - 分隔玩家的主要内容,如果未能解决你的问题,请参考以下文章
使用Cocos2d-Javascript和Node.js的多人游戏
node.js 中的多人游戏架构 - 与 Redux 的状态管理和同步