使用Node.JS,MongoDB和Socket.IO的实时多人游戏:游戏循环和异步调用

时间:2015-08-21 10:06:20

标签: node.js mongodb socket.io game-loop

我目前正在使用Node.JS,MongoDB和Socket.IO构建HTML5游戏。这个项目的目的并不是真正创造一个完整的,完全可玩的游戏,而是理解和实现多人游戏编程的一些基本概念并习惯MongoDB。

这是我使用的基本服务器架构。服务器通过Socket.IO监听客户端,每次收到消息时,它都会将其推送到队列。每当玩家想要移动或者以某种方式有效地改变游戏时,就会收到消息。我真的很模糊,因为向你展示这个游戏的细节并不重要。因此,服务器接收来自所有客户端的消息,并将其保留在内存中一段时间​​。

服务器每隔50ms顺序处理队列中的所有消息并使游戏状态提前,将更改广播到客户端,然后清空队列并再次开始侦听客户端。

我在构建这个游戏循环时遇到了一些困难,因为我并不确定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是否适合这项工作。

我使用MongoDB的官方Node.JS驱动程序,因为我对嵌套文档比对象数据建模更感兴趣。

在这种情况下,你有关于构建顺序游戏循环的线索吗?或者我是否在其目的之外的情况下使用MongoDB?

1 个答案:

答案 0 :(得分:1)

似乎相当直接。

解决方案不是使用for循环,因为您只想在上一个消息完成之后启动正在处理的下一个消息。为此,使用asynceachSeries函数等库可能更容易。

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);
}