2013-10-26 3 views
0

게임에서 저는 비동기식과 실시간 턴 기반 매치 중 하나를 선택할 수있는 가능성을 제공하고자합니다. 후자에서 빠진 한 가지 점은 누가 첫 번째 턴을 가지고 있는지 어떻게 알 수 있습니까? 나는 누가 먼저 연결 됐는지 탐지하고 그 플레이어의 턴을 자동으로 설정하는 방법을 찾고 있습니다. 불행하게도, 두 선수가 일치하는 것을 찾은 직후부터 두 선수가 동시에 연결되어있는 것처럼 보입니다. expectedPlayersCount는 두 선수 모두에게 1을, didChangeState 이벤트에서 두 선수 모두 똑같은 변수가 0을 산출합니다. 그래서 나는 모든 것이 동시에 일어나는 것처럼 보이기 때문에 누가 그 경기에서 제일 먼저 왔는지 말할 방법이 없다. 임시 수정으로 ID를 사용하고 있습니다. ID가 가장 낮은 것은 첫 번째 턴이있는 ID입니다. 그러나이 방법을 사용하면 플레이어 A가 플레이어 B를 상대 할 때 항상 첫 번째 턴을 갖게 될 것이므로 내 게임에서 작은 이점을 나타 내기 때문에 더 좋은 방법을 찾으려고합니다.처음에 연결되어있는 플레이어를 결정하십시오.

이 방법은 내가 새 게임을 시작할 때 부르는 것입니다. 게임 중앙 래퍼에 의해 반환 된 게임이 GKMatch 또는 GKTurnBasedMatch인지 여부를 지정하기 위해 realtime bool 값을 전달합니다.

//Calculate the level group to find other players in the same group 
NSInteger levelGroup = (self.player.levelValue/STLevelSkillInterval) * STLevelSkillInterval; 

//Find a match for the local player 
[self.gameCenter findMatchWithPlayerAttributes:levelGroup realTime:realTime group:0 onCompletion:^(GKTurnBasedMatch *turnMatch, GKMatch *realTimeMatch) { 

    [self handleTurnMatchFound:turnMatch realTimeMatch:realTimeMatch completionBlock:onCompletion]; 

}]; 

...

여기에이 방법은 일치를 발견 한 후 게임 센터의 응답을 처리 할 책임이있다. create and synchronize 메서드는 CoreData에 일치 인스턴스를 저장하고 Game Center와 백엔드에서 해당 정보를 가져 와서 데이터를 채 웁니다. 따라서 예상되는 플레이어 수가 0에 도달하면 경기가 시작될 수 있기 때문에 즉시 완료 블록을 호출합니다. 그렇지 않으면 나중에 완료 블록을 저장하므로 나중에 다른 플레이어가 경기에 연결할 때 사용할 수 있습니다. 이 부분의 문제는 두 선수 중 어느 누구도 0이 아니라는 것입니다.

- (void)handleTurnMatchFound:(GKTurnBasedMatch *)turnMatch realTimeMatch:(GKMatch *)realTimeMatch completionBlock:(void(^)(STMatch *match, NSError *error))onCompletion 
{ 
    if (turnMatch != nil) 
    { 
     [self createAndSynchronizeLocalMatch:turnMatch onCompletion:^(STMatch *localMatch) { 

      onCompletion(localMatch, nil); 

     }]; 
    } 
    else if (realTimeMatch != nil) 
    { 
     [self createAndSynchronizeRealTimeLocalMatch:realTimeMatch onCompletion:^(STMatch *localMatch) { 

      if (realTimeMatch.expectedPlayerCount == 0) 
      { 
       onCompletion(localMatch, nil); 
      } 
      else 
      { 
       self.findRealTimeMatchCompletionBlock = onCompletion; 
      } 

     }]; 
    } 
    else 
    { 
     onCompletion(nil, nil); 
    } 
} 

은 ...

이 플레이어의 상태 변경을 처리하는 방법이다. 그래서 기본적으로 여기에서는 연결된 플레이어의 값으로 실시간 일치의 로컬 인스턴스를 업데이트 한 다음 이전에 저장 한 완료 블록을 호출합니다.

- (void)match:(GKMatch *)match player:(NSString *)playerID didChangeState:(GKPlayerConnectionState)state 
{ 
    if (state == GKPlayerStateConnected) 
    { 
     STMatchParticipant *placeholderParticipant = [self.realTimeMatch getMatchParticipantWithPlayerId:nil]; 
     placeholderParticipant.playerId = playerID; 
     placeholderParticipant.statusValue = GKTurnBasedParticipantStatusActive; 

     //This will sync the information for the connected player only 
     [self syncAllPlayerInfoForRealTimeMatchOnCompletion:^(NSArray *players) { 

      self.findRealTimeMatchCompletionBlock(self.realTimeMatch, nil); 

     }]; 
    } 
    else 
    { 
     //Notify the observers that the participant has disconnected from the match 
     STMatchParticipant *participant = [self.realTimeMatch getMatchParticipantWithPlayerId:playerID]; 

     for (id<STTurnBasedMatchDelegate> observer in self.matchesObservers) 
     { 
      if ([observer respondsToSelector:@selector(realTimeMatch:participantDidDisconnect:)]) 
      { 
       [observer realTimeMatch:self.realTimeMatch participantDidDisconnect:participant]; 
      } 
     } 
    } 
} 

모든 의견을 부탁드립니다.

+0

작성한 코드 관련 문제는 특정 문제를 설명해야하며이를 재현 할 수있는 유효한 코드가 포함되어야합니다. –

+0

죄송합니다. 내 질문을 편집하고 코드에 몇 가지 주석을 달았습니다. 감사. – mdonati

답변

1

누가 먼저 연결했는지 확인하려고하는 대신 모든 플레이어가 arc4random을 사용하여 임의의 번호를 선택하게하는 것이 어떻습니까?

int randomNumber = arc4random%1000000; 

가장 큰 번호의 플레이어가 먼저 재생할 수 있습니다. 모든 플레이어가 서로를 무작위로 전송하여 모든 사람이 누가 먼저인지 비교하고 결정할 수 있도록해야합니다. 위의 예에서 범위는 최대 백만이 될 것이므로 동일한 난수를 선택하는 두 플레이어의 확률은 낮습니다.

두 명의 플레이어가 동일한 난수를 선택하면 해당 플레이어 ID의 해시를 계산하고 큰 해시를 가진 플레이어를 먼저 계산할 수 있습니다.

if ([GKLocalPlayer localPlayer].playerID.hash > otherPlayerId.hash) 

해시 충돌이 발생할 확률은 매우 낮습니다. playerId 문자열이 짧기 때문입니다. 이 충돌을 여전히 확인하고 적절하게 처리 할 수 ​​있습니다 (어쩌면 다시 해시로).