Многопользовательская игра в реальном времени с использованием Node.JS, MongoDB и Socket.IO: игровой цикл и асинхронные вызовы

В настоящее время я создаю игру HTML5, используя Node.JS, MongoDB и Socket.IO. Целью этого проекта на самом деле является не создание законченной, полностью играбельной игры, а скорее понимание и реализация некоторых основных концепций программирования многопользовательских игр и привыкание к MongoDB.

Вот базовая архитектура сервера, с которой я работал. Сервер слушает клиентов через Socket.IO и каждый раз при получении сообщения помещает его в очередь. Сообщение поступает всякий раз, когда игрок хочет переместиться или эффективно изменить игру. Я остаюсь очень расплывчатым, потому что на самом деле не имеет значения, чтобы показать вам в деталях, что это за игра. Итак, сервер получает сообщения от всех клиентов и хранит их в памяти определенное время.

Каждые 50 мс сервер последовательно обрабатывает все сообщения в очереди и продвигает состояние игры, транслирует изменения клиентам, а затем очищает очередь и снова начинает слушать клиентов.

У меня возникли некоторые трудности с созданием этого игрового цикла, так как я не совсем уверен, что делает MongoDB и делает ли он это вовремя, поскольку все вызовы являются чистыми асинхронными. Допустим, в моем игровом цикле находится следующий код, вот что меня беспокоит:

for (var i=0; i<queue.length; i++) {
    if(queue[i].message.type === "move") {
        //The server has first to ensure that the player can effectively move, 
        //thus making a query to MongoDB. Once the result has been retrieved,
        //the server makes an update in MongoDB with the new player position
    }
    //At this point, due to the async nature of MongoDB, 
    //I cannot ensure that the queries have been executed nor that the message was effectively handled
}
//Here again, I cannot ensure that the game state gracefully advanced 
//and then I cannot broadcast it.

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

Я использую официальный драйвер Node.JS для MongoDB, поскольку меня больше интересуют вложенные документы, чем моделирование объектных данных.

Есть ли у вас какие-либо подсказки по построению последовательного игрового цикла в этом случае? Или я использую MongoDB не по назначению?


person Maxime Piraux    schedule 21.08.2015    source источник
comment
добавил пример к моему ответу   -  person smremde    schedule 21.08.2015


Ответы (1)


Кажется довольно прямолинейным.

Решение состоит не в том, чтобы использовать цикл for, так как вы хотите начать обработку следующего сообщения только после завершения предыдущего. Для этого, вероятно, проще использовать библиотеку типа async и функцию eachSeries.

https://github.com/caolan/async#each

async.eachSeries(queue, processMessage, allDone);

function processMessage(message, callback) {
  // do stuff with message, don't forget to call callback when you have complete all async calls and are done processing the message!

  // eg

  if(message.type === "move") {
    mongo.insert({player: message.player, x:message.x, y:message.y}, function (err, res) {
      // error check etc
      callback();
    }
  }
}

function allDone() {
  // called when all messages have been proccessed!
  // setTimeout(processNewQueue, 50);
}
person smremde    schedule 21.08.2015
comment
Спасибо за ваш ответ! Это должно соответствовать моей проблеме, я думаю, я немного заблудился в асинхронных джунглях и действительно не знал, какой инструмент использовать для решения этой проблемы. Я немного жду, прежде чем принять ваш ответ, поэтому я могу попробовать его завтра и подтвердить, что он подходит для моей проблемы. Спасибо за ваш интерес к моему вопросу. - person Maxime Piraux; 21.08.2015