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

发布于 2024-12-29 10:58:11 字数 215 浏览 1 评论 0原文

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

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

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

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.

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

够钟 2025-01-05 10:58:11

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

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

});

然后每隔 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://fabiensanglad.net/quakeSource/quakeSourcePrediction.php

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

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

《Age of》中的多人游戏技术帝国:

<一href="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#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

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:

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:

{
  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.

My reputation doesn't allow me to post all the links, so I have attached them here:
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/

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

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

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

You can also read my article about optimizing bandwidth usage

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.

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

无力看清 2025-01-05 10:58:11

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

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

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

我建议您查看 Maple.js

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

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.

I recommend you take a look at Maple.js

优雅的叶子 2025-01-05 10:58:11

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

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

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.

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文