Многопользовательская JavaScript-игра, созданная с Node.JS - Разделение игроков - PullRequest
13 голосов
/ 27 января 2012

У меня есть вопрос, на который я не могу найти ответ.

Я экспериментирую с созданием многопользовательской игры с Node.JS и Socket.IO. В качестве первого эксперимента я построил чат-комнату, поэтому у меня работают трансляции и т. Д. Теперь я нахожусь в точке, где я хочу, чтобы что-то работало с Canvas.

Проблема, с которой я сталкиваюсь, заключается в том, чтобы свести голову с несколькими независимыми игроками. Я знаю, что каждый игрок отправит свои x, y шнуры на сервер, и сервер будет транслировать их, но как клиент узнает, сколько игроков отображать, я предполагаю, что они должны храниться где-то в массиве.

Ответы [ 3 ]

39 голосов
/ 27 января 2012

Моя реализация будет очень наивной и упрощенной, без компенсации отставания, экстраполяции и тому подобного, но она должна указывать на общую концепцию «многопользовательской игры» с узлом.

Я думаю, что самый простой подход - это иметь ассоциативный массив, содержащий игроков (сущностей) как на клиенте, так и на сервере. Затем со стороны клиента вы отправляете команды типа {action: "move", target:[32, 100]} и обрабатываете эту команду с помощью серверной логики (где работает настоящая игра). Каждому сокету on connection вы должны назначить объект игрока или идентификатор, чтобы вы могли получить к нему доступ, например:

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

Общее введение в многопользовательские концепции Гленна Фидлера:

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

Многопользовательские приемы в Age of Empires:

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's Wetzel Mapple.js - это большая куча знаний.

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

11 голосов
/ 27 января 2012

Игроки не отправляют свои координаты x, y на сервер, что позволяет обманывать путем ручной отправки координат.

Каждый игрок отправляет на сервер события «перемещение влево / вправо / вверх / вниз». Затем сервер обновляет позиции и периодически транслирует положение (или дельты в позиции) всех игроков.

Каждый клиент затем берет все эти дельты игрока и отображает их. С точки зрения реализации на стороне клиента у меня будет какой-то объект Board / Map, и у него будет список RenderableEntities. Затем я просто обновляю RenderableEntities новыми позициями и периодически перерисовываю все сущности.

Я рекомендую вам взглянуть на Maple.js

1 голос
/ 23 мая 2017

Другой способ синхронизировать координаты X & Y каждого игрока - использовать Lance .Это библиотека JavaScript с открытым исходным кодом, которая обрабатывает коррекцию положения для нескольких игроков с авторитетным сервером.

Будет полезно, если вам нужно синхронизировать другие вещи, помимо координат, например, имя объекта или свойства аватара.Или если у ваших игроков есть скорости.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...