我想用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函数。这个功能只是检查每一个房间的时间限制,如果房间太多,我认为它在服务器上负载很重,所以我正在寻求更好的方法。
谢谢
答案 0 :(得分:0)
如果您想扩展到Node.js,如果您想要可扩展的精确计时,setInterval可能不是理想的解决方案。
现在迭代所有房间可能会很好,因为在阻塞迭代导致性能问题之前,您将需要大量的房间。
缓解这些问题的一些方法是水平扩展Node集群并在多个Node进程之间分配房间,或者通过检查move事件监听器中的移动是否无效来实现对无效移动的延迟检查,而不是一个setInterval。