Ios 避免冲突,当;“匹配”;多人游戏用户

Ios 避免冲突,当;“匹配”;多人游戏用户,ios,swift,firebase,multiplayer,pubnub,Ios,Swift,Firebase,Multiplayer,Pubnub,我尝试了FireBase和PubNub来创建这个简单的多人游戏。仅由两名玩家创建。一个大问题(也是合理的)是用户之间的冲突。让我解释一下: 每个“游戏”只有两个玩家(不是更多)。如果4名玩家同时登录。每个玩家搜索一个“匹配”。玩家一可能和玩家二匹配,而玩家二可能和玩家三匹配,依此类推 我如何避免它,并保证每个玩家将获得一个唯一的匹配?或者换句话说,防止将一个用户与多个用户匹配匹配 [p1]-[p2]-[p3]-[p4]-[p5]-等等 好的,让奇数玩家(N)和下一个偶数玩家(N+1)匹配 当然,

我尝试了FireBase和PubNub来创建这个简单的多人游戏。仅由两名玩家创建。一个大问题(也是合理的)是用户之间的冲突。让我解释一下:

每个“游戏”只有两个玩家(不是更多)。如果4名玩家同时登录。每个玩家搜索一个“匹配”。玩家一可能和玩家二匹配,而玩家二可能和玩家三匹配,依此类推


我如何避免它,并保证每个玩家将获得一个唯一的匹配?或者换句话说,防止将一个用户与多个用户匹配匹配

[p1]-[p2]-[p3]-[p4]-[p5]-等等

好的,让奇数玩家(N)和下一个偶数玩家(N+1)匹配

当然,P5会独处,应该等待下一轮,让他成为该轮的P1。这样他就不用等两回合了

您可以为这些对创建一个元组,但我会让
Player
类也有一个
oponent
类型的字段
Player

edit1:您可以在规则的玩家数组中跟踪原始队列。一旦阵列达到所需大小,您就会触发上述算法,该算法停止更改为当前玩家池的功能,所有匹配都将确定

怠速检查

好的,让玩家进入队列,然后显示一个计时器/空插槽计数器,这样他们就有了
反馈
他们需要等待多长时间

比赛一开始,你就让他们锁定(传奇联盟也是这样做的) 如果有一个或多个玩家未锁定,您可以重新开始排队过程,可以减少计时器,这样玩家就不必等待太长时间

如果你让这个时间为基础(而不是插槽为基础),那么如果1个玩家没有响应(比如说P2),你移动最后一个玩家(P5)到他的插槽(P5现在是P2),每个人都可以玩


如果您有更多问题,我将编辑此答案。

匹配

[p1]-[p2]-[p3]-[p4]-[p5]-等等

好的,让奇数玩家(N)和下一个偶数玩家(N+1)匹配

当然,P5会独处,应该等待下一轮,让他成为该轮的P1。这样他就不用等两回合了

您可以为这些对创建一个元组,但我会让
Player
类也有一个
oponent
类型的字段
Player

edit1:您可以在规则的玩家数组中跟踪原始队列。一旦阵列达到所需大小,您就会触发上述算法,该算法停止更改为当前玩家池的功能,所有匹配都将确定

怠速检查

好的,让玩家进入队列,然后显示一个计时器/空插槽计数器,这样他们就有了
反馈
他们需要等待多长时间

比赛一开始,你就让他们锁定(传奇联盟也是这样做的) 如果有一个或多个玩家未锁定,您可以重新开始排队过程,可以减少计时器,这样玩家就不必等待太长时间

如果你让这个时间为基础(而不是插槽为基础),那么如果1个玩家没有响应(比如说P2),你移动最后一个玩家(P5)到他的插槽(P5现在是P2),每个人都可以玩

如果您有更多问题,我将编辑此答案。

使用Firebase,这将是一个优雅解决方案的关键

如果您愿意设置node.js脚本或其他服务器端工作程序,这相当简单。当球员想要比赛时,他们会写信给“大厅”。服务器脚本将执行匹配并写回他们将加入的“游戏室”。结构基本上是这样的:

 /games/$game_id/users/user1/<user_id>
 /games/$game_id/users/user2/<user_id>

 /lobby/$user_id/false    (an unmatched user)
 /lobby/$user_id/$game_id (a matched user)
/games/$game\u id/users/user1/
/games/$games\u id/users/user2/
/大厅/$user\u id/false(不匹配的用户)
/大厅/$user\u id/$game\u id(匹配用户)
现在,当客户想要加入游戏时,他们只需向大厅写信,然后等待服务器为他们分配游戏id:

var ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com/");
var lobbyRef = ref.child('lobby/' + <my user id>);
lobbyRef.set(false); // I want to join a game
lobbyRef.on('value', function(snap) {
   if( snap.val() !== null ) {
      console.log('I joined a game!', snap.val());
   }
});
var ref=新Firebase(“https://.firebaseio.com/");
var lobbyRef=ref.child('lobby/'+);
lobbyRef.set(false);//我想参加一个游戏
lobbyRef.on('value',函数(snap){
如果(snap.val()!==null){
console.log('我参加了一个游戏!',snap.val());
}
});
服务器几乎同样简单。假设node.js:

var ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com/");
var lobbyRef = ref.child('lobby');
var gamesRef = ref.child('games');
var player1 = null;

// listen for requests to join
lobbyRef.on('child_added', function(snap) {
   // assign as player1 if nobody is waiting
   if( !player1 ) {
      player1 = snap.ref();
   }
   // if someone is already waiting, assign both players a room
   else {
      var player2 = snap.ref();
      var gameRef = gamesRef.push({ 
         players: {
            player1: player1.key(),
            player2: snap.key()
         }
      }, function(err) {
        if( err ) { throw err; } // a bug
        // let the players know they have been matched and which room to join
        player1.set(gameRef.key());
        player2.set(gameRef.key());
      });
   }
});
var ref=新Firebase(“https://.firebaseio.com/");
var lobbyRef=ref.child('lobbyRef');
var gamesRef=ref.child(“游戏”);
var player1=null;
//侦听加入请求
lobbyRef.on('child_added',函数(snap){
//如果无人等待,则指定为播放机1
如果(!player1){
player1=snap.ref();
}
//如果有人已经在等待,则为两名玩家分配一个房间
否则{
var player2=snap.ref();
var gameRef=gamesRef.push({
玩家:{
player1:player1.key(),
player2:snap.key()
}
},函数(err){
if(err){throw err;}//一个bug
//让球员们知道他们已经匹配好了,应该加入哪个房间
player1.set(gameRef.key());
player2.set(gameRef.key());
});
}
});
显然,有一些工作可以使所有这些容错,并需要防止作弊

完全在客户机上完成这项工作稍微复杂一些,但肯定是可以管理的

让每位玩家尝试与大厅中的任何人进行匹配。如果大厅里没有人,那就在那儿等着。这样做是为了防止冲突

var ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com/");
var lobbyRef = ref.child('lobby');

function waitInLobby() {
   lobbyRef.once('value', lobbyUpdated);
}

function lobbyUpdated(snap) {
   if( snap.val() === null ) {
      // lobby is empty, so join and wait
      var ref = lobbyRef.child('<my user id>').push(false);
      ref.on('value', someoneMatchedMe);

      function someoneMatchedMe(snap) {
         if( snap.val() !== false ) {
            console.log('I got matched in room', snap.val());
            ref.off('value', someoneMatchedMe); // stop monitoring
            snap.ref().remove(); // leave the lobby
         }
      }
   }
   else {
      // lobby is not empty, so try to match someone
      var possibles = [];
      snap.forEach(function(ss) {
         possibles.push(ss.ref());
      });
   }
}

function matchUser(possibles) {
   if( !possibles.length ) { waitInLobby(); }
   var opponentRef = lobbyRef.child(possibles.shift());
   opponentRef.transaction(function(currentVal) {
      if( currentVal !== false ) {
         // already claimed, start over
         matchUser(possibles);
      }
   });
}
var ref=新Firebase(“https://.firebaseio.com/");
var lobbyRef=ref.child('lobbyRef');
函数waitInLobby(){
lobbyRef.once('value',LobbyUpdate);
}
函数说话人更新(快照){
if(snap.val()==null){
//大厅是空的,所以加入一个