如何在Socket.io,Nodejs中为每个房间设置计时器

时间:2015-02-14 21:03:20

标签: node.js sockets timer socket.io

我想用socket.io和nodejs创建一个回合制游戏。有一些房间和每个 房间应该拥有它自己的计时器,因为玩家的动作有时间限制所以我想知道我怎么能处理这个,也许是愚蠢的方式或者为每个房间设置一个计时器是不切实际的?我不知道。请指导我:))

我的代码是玩家移动和其他东西:

var server = require('http').Server();
var socketIO = require('socket.io');
var io = socketIO.listen(server);


//var redis = require("redis"),
//client = redis.createClient();
var Room = require("./Room.js").Room;

var server_port = process.env.OPENSHIFT_NODEJS_PORT || 8080;
var server_ip_address = process.env.OPENSHIFT_NODEJS_IP || '127.0.0.1';


var connected_players = 0;
var players = {};
var rooms = {};

io.sockets.on('connection', function(socket){
  connected_players = connected_players + 1;
  console.log("New Player Connected :) \n" + "Total Number of Connected Players = " + connected_players );
  players[socket.id] = socket;
  socket.emit("sessionEv", {"session_id" : socket.id});
  socket.on("joining", function(data){


//SOME CODE FOR JOINING !!

  });

  socket.on('disconnect', function(){

      console.log("disconnect" + this.id + " ; playerid = " + connected_players);
      delete players[socket.id];

      connected_players = connected_players - 1 ;


  });

  socket.on("move", function(data){
    var tempRoom = rooms[socket.room_name];
    var current_turn = tempRoom.Turn;
    console.log("on Move :" + data.handId + ":" + data.moveType);
    if (current_turn == data.handId ){ 
      console.log("correct move from :" + data.handId);
      //Calculating next turn;
      if(data.moveType == 1){
        while(true){
          current_turn = current_turn + tempRoom.Clock_Flag ;

          if(current_turn > tempRoom.Max*2){
            current_turn = current_turn%(tempRoom.Max * 2);
          }

          if(current_turn === 0){
            current_turn = tempRoom.Max * 2 ;
          }

          if(!checkLoseHand(current_turn, tempRoom)){
            break;
          }
        }
      }
      if(data.moveType === 2){
        tempRoom.Clock_Flag = tempRoom.Clock_Flag * - 1;
        while(true){
          current_turn = current_turn + tempRoom.Clock_Flag ;

          if(current_turn > tempRoom.Max*2){
            current_turn = current_turn%(tempRoom.Max * 2);
          }


          if(current_turn === 0){
            current_turn = tempRoom.Max * 2 ;

          }
          if(!checkLoseHand(current_turn, tempRoom)){
            break;
          }
        }
      }
      if(data.moveType == 3 ){
        while(true){
          current_turn = current_turn + tempRoom.Clock_Flag ;

          if(current_turn > tempRoom.Max * 2){
            current_turn = current_turn%(tempRoom.Max * 2);
          }


          if(current_turn === 0){
            current_turn = tempRoom.Max * 2 ;
          }

          if(!checkLoseHand(current_turn, tempRoom)){
            break;
          }
        }  
        while(true){
          current_turn = current_turn + tempRoom.Clock_Flag ;

          if(current_turn > tempRoom.Max * 2){
            current_turn = current_turn%(tempRoom.Max * 2);
          }


          if(current_turn === 0){
            current_turn = tempRoom.Max * 2 ;
          }

          if(!checkLoseHand(current_turn, tempRoom)){
            break;
          }

        }





    }
    tempRoom.Turn = current_turn;
    var d = new Date();
    var n = d.getSeconds();
    tempRoom.lastmove = n;
    tempRoom.start = true;
    console.log("next turn = " + current_turn);
    io.sockets.in(socket.room_name).emit("move", {"handId" : data.handId , "moveType" : data.moveType, "turn" : current_turn});




  }
    else{
      io.sockets.in(socket.room_name).emit('lose', {"handId" : data.handId} );
      socket.broadcast.to(socket.room_name).volatile.emit("move", {"handId" : data.handId , "moveType" : data.moveType, "turn" : current_turn});
      tempRoom.losers_hand.push(data.handId);

    }
  //}
  });

});

server.listen(server_port , server_ip_address);



playerById =  function(id) {
  var i;
  for (i = 0; i < players.length; i++) {
    if (players[i].id == id)
      return players[i];
  }

  return false;
};

checkLoseHand = function(id, tempRoom ){
  for (i = 0; i < tempRoom.losers_hand.length; i++) {
    if( tempRoom.losers_hand[i] == id){
      return true; 
    }

  }
  return false;
};

function get_users_by_room(nsp, room) {
  var users = [];
  for (var id in io.of(nsp).adapter.rooms[room]) {
    users.push(io.of(nsp).adapter.nsp.connected[id]);
  }
  return users.length;
}

setInterval(function(){
    var d = new Date();
    for (var key in rooms)
    {
        console.log(key);
        console.log(d.getSeconds());
        console.log(rooms[key].lastmove);
        if(Math.abs(d.getSeconds() - rooms[key].lastmove) > 5 && rooms[key].start )
        {
            io.sockets.in(key).emit('lose', {"handId" : rooms[key].Turn } );
            //inja bayad turn badi ham ersal she .
        }
    } 
    //console.log("here");
}, 1000);

当MOVE EVENT收到时我将该移动发送给其他玩家并计算下一回合(NOW计时器应该开始计算当前回合玩家的秒数) 如果玩家在允许的时间内移动没有任何事情发生,但如果不是,他必须离开游戏室。

正如您所看到的,我在代码末尾编写了一个SetInteval函数。这个功能只是检查每一个房间的时间限制,如果房间太多,我认为它在服务器上负载很重,所以我正在寻求更好的方法。

谢谢

1 个答案:

答案 0 :(得分:0)

如果您想扩展到Node.js,如果您想要可扩展的精确计时,setInterval可能不是理想的解决方案。

现在迭代所有房间可能会很好,因为在阻塞迭代导致性能问题之前,您将需要大量的房间。

缓解这些问题的一些方法是水平扩展Node集群并在多个Node进程之间分配房间,或者通过检查move事件监听器中的移动是否无效来实现对无效移动的延迟检查,而不是一个setInterval。