使用 Node.JS 构建的多人 JavaScript 游戏 - 分离玩家
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9033166/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Multiplayer JavaScript game built with Node.JS - Separating players
提问by Henryz
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 构建多人游戏。我已经建立了一个聊天室作为我的第一个实验,所以我有广播工作等。现在我想用 Canvas 做一些事情。
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 线发送到服务器,服务器将广播这些线,但是客户端如何知道要显示多少玩家,我猜他们必须存储在某个数组中。
回答by rezoner
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]}
命令并使用服务器逻辑(实际游戏运行的地方)处理此命令。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();
}
});
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:
Glenn Fiedler 对多人游戏概念的一般介绍:
Some multiplayer techniques from Quake: This will give u a clue about interpolation and extrapolation(prediction)
来自 Quake 的一些多人游戏技术:这将提供有关插值和外推(预测)的线索
http://fabiensanglard.net/quakeSource/quakeSourcePrediction.php
http://fabiensanglad.net/quakeSource/quakeSourcePrediction.php
Valve's article about latency compensation and general optimisations:
Valve 关于延迟补偿和一般优化的文章:
Multiplayer techniques in Age of Empires:
帝国时代的多人游戏技巧:
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.js,这是一大堆知识。
回答by Raynos
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
我建议你看看Maple.js
回答by Gary Weiss
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 坐标的另一种方法是使用Lance。它是一个开源 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.
如果您需要同步坐标以外的其他内容,例如对象名称或头像属性,这将非常有用。或者如果你的球员有速度。