私が取り組んでいるゲームでは、ユーザーが非同期とリアルタイムのターンベースの対戦を選択できるようにしたいと考えています。後者に欠けていることの 1 つは、誰が最初のターンを獲得したかをどうやって知るかということです。誰が最初に接続したかを検出し、そのプレーヤーのターンを自動的に設定する方法を見つけようとしています。残念ながら、マッチを見つけた直後に expectedPlayersCount が両方のプレーヤーに対して 1 を生成し、 didChangeState イベントで同じ変数が両方に対して 0 を生成するため、両方のプレーヤーが同時に接続されているようです。そのため、すべてが同時に行われるように見えるため、誰が最初に試合に参加したかを知る方法はありません. 一時的な修正として、私は彼らの ID を使用しています。最も低い ID を持つものは、最初のターンを持つものです。しかし、私は'
このメソッドは、新しいゲームを開始するときに呼び出すものです。ゲーム センター ラッパーによって返されるゲームが 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 および synchronize メソッドは、マッチ インスタンスを CoreData に格納し、Game Center とバックエンドから対応する情報をフェッチしてそのデータを埋めます。その時点で予想されるプレイヤー数が 0 に達した場合、試合を開始できるので、すぐに完了ブロックを呼び出します。それ以外の場合は、完了ブロックを保存して、後で他のプレイヤーが試合に接続したときに使用できるようにします。その部分の問題は、2 人のプレイヤーのどちらでも、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];
}
}
}
}
コメントをいただければ幸いです。