0

私は現在 Game Center Multiplayer に取り組んでおり、いくつかの障害に遭遇しました。現在、私が怒鳴っているコードは、ユーザーが仲人ビューを表示し、試合をうまく開始することを認証します。ただし、友人を試合に招待しようとすると、試合をプレイするように求めるアラート ビューが表示され、それを受け入れると、マッチメイキング ビュー コントローラーが表示され、他のデバイスで他のプレイヤーを待っていると表示され、待機していると表示されます。他のプレイヤーが応答するため。最終的に、しばらくすると、招待がキャンセルされたと表示されます。私はシミュレータを使用していません.2つのデバイスがあり、両方とも別々のゲームセンタープロファイルがあります. 1 つは IOS 4.2 で、もう 1 つは IOS 4.3 です。何が問題なのかわかりません。私のマルチプレイヤー コードはすべて次のとおりです。また、いずれかのデバイスにデータを送信するために、それについて詳しく知るための良いサイトを知りたいです. 皆さんが思いつくものを見るのが楽しみです。ありがとう

ViewController.h

 #import <Foundation/Foundation.h>
 #import <GameKit/GameKit.h>

@protocol GCHelperDelegate 
- (void)matchStarted;
- (void)matchEnded;
- (void)match:(GKMatch *)match didReceiveData:(NSData *)data fromPlayer:(NSString *)playerID;
- (void)inviteReceived;
@end

@interface ViewController : UIViewController <GKMatchmakerViewControllerDelegate, GKMatchDelegate, GCHelperDelegate, GameCenterManagerDelegate> {
 BOOL gameCenterAvailable;
BOOL userAuthenticated;

UIViewController *presentingViewController;
GKMatch *match;
BOOL matchStarted;
id <GCHelperDelegate> delegate;
NSMutableDictionary *playersDict;
GKInvite *pendingInvite;
NSArray *pendingPlayersToInvite;

}

@property (assign, readonly) BOOL gameCenterAvailable;
@property (retain) GKMatch *match;
@property (assign) id <GCHelperDelegate> delegate;
@property (retain) NSMutableDictionary *playersDict;
@property (retain) GKInvite *pendingInvite;
@property (retain) NSArray *pendingPlayersToInvite;

- (void)authenticateLocalUser;
- (void)findMatchWithMinPlayers:(int)minPlayers maxPlayers:(int)maxPlayers viewController:(UIViewController *)viewController delegate:(id<GCHelperDelegate>)theDelegate;

@end

そしてView Controller.m

 //ViewController.m Multyplayer


#pragma mark Initialization

- (BOOL)isGameCenterAvailable {
// check for presence of GKLocalPlayer API
Class gcClass = (NSClassFromString(@"GKLocalPlayer"));

// check if the device is running iOS 4.1 or later
NSString *reqSysVer = @"4.1";
NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
BOOL osVersionSupported = ([currSysVer compare:reqSysVer 
                                       options:NSNumericSearch] != NSOrderedAscending);

return (gcClass && osVersionSupported);
}

- (id)init {
if ((self = [super init])) {
    gameCenterAvailable = [self isGameCenterAvailable];
    if (gameCenterAvailable) {
        NSNotificationCenter *nc = 
        [NSNotificationCenter defaultCenter];
        [nc addObserver:self 
               selector:@selector(authenticationChanged) 
                   name:GKPlayerAuthenticationDidChangeNotificationName 
                 object:nil];
    }
}
return self;
}

#pragma mark Internal functions

- (void)authenticationChanged {    


if ([GKLocalPlayer localPlayer].isAuthenticated && !userAuthenticated) {
    NSLog(@"Authentication changed: player authenticated.");
    userAuthenticated = TRUE;  

    [GKMatchmaker sharedMatchmaker].inviteHandler = ^(GKInvite *acceptedInvite, NSArray *playersToInvite) {

        NSLog(@"Received invite");
        self.pendingInvite = acceptedInvite;
        self.pendingPlayersToInvite = playersToInvite;
        [delegate inviteReceived];

    };

} else if (![GKLocalPlayer localPlayer].isAuthenticated && userAuthenticated) {
    NSLog(@"Authentication changed: player not authenticated");
    userAuthenticated = FALSE;
}

    }

- (void)lookupPlayers {

NSLog(@"Looking up %d players...", match.playerIDs.count);
[GKPlayer loadPlayersForIdentifiers:match.playerIDs withCompletionHandler:^(NSArray *players, NSError *error) {

    if (error != nil) {
        NSLog(@"Error retrieving player info: %@", error.localizedDescription);
        matchStarted = NO;
        [delegate matchEnded];
    } else {

        // Populate players dict
        self.playersDict = [NSMutableDictionary dictionaryWithCapacity:players.count];
        for (GKPlayer *player in players) {
            NSLog(@"Found player: %@", player.alias);
            [playersDict setObject:player forKey:player.playerID];
        }

        // Notify delegate match can begin
        matchStarted = YES;
        [delegate matchStarted];

    }
}];

}

#pragma mark User functions

- (void)authenticateLocalUser { 

if (!gameCenterAvailable) return;

NSLog(@"Authenticating local user...");
if ([GKLocalPlayer localPlayer].authenticated == NO) {     
    [[GKLocalPlayer localPlayer] authenticateWithCompletionHandler:nil];        
} else {
    NSLog(@"Already authenticated!");
}
}


- (void)findMatchWithMinPlayers:(int)minPlayers maxPlayers:(int)maxPlayers viewController:(UIViewController *)viewController delegate:(id<GCHelperDelegate>)theDelegate {

if (!gameCenterAvailable) return;

matchStarted = NO;
self.match = nil;
self.presentingViewController = viewController;
delegate = theDelegate;

if (pendingInvite != nil) {

    GKMatchmakerViewController *mmvc = [[[GKMatchmakerViewController alloc] initWithInvite:pendingInvite] autorelease];
    mmvc.matchmakerDelegate = self;
    [self presentModalViewController:mmvc animated:YES];

    self.pendingInvite = nil;
    self.pendingPlayersToInvite = nil;

} else {

    GKMatchRequest *request = [[[GKMatchRequest alloc] init] autorelease]; 
    request.minPlayers = minPlayers;     
    request.maxPlayers = maxPlayers;
    request.playersToInvite = pendingPlayersToInvite;

    GKMatchmakerViewController *mmvc = [[[GKMatchmakerViewController alloc] initWithMatchRequest:request] autorelease];    
    mmvc.matchmakerDelegate = self;

    [self presentModalViewController:mmvc animated:YES];

    self.pendingInvite = nil;
    self.pendingPlayersToInvite = nil;

}
}           

#pragma mark GKMatchmakerViewControllerDelegate

// The user has cancelled matchmaking
- (void)matchmakerViewControllerWasCancelled:(GKMatchmakerViewController *)viewController {
[self dismissModalViewControllerAnimated:YES];
}

// Matchmaking has failed with an error
- (void)matchmakerViewController:(GKMatchmakerViewController *)viewController didFailWithError:(NSError *)error {
[self dismissModalViewControllerAnimated:YES];
NSLog(@"Error finding match: %@", error.localizedDescription);    
}

// A peer-to-peer match has been found, the game should start
- (void)matchmakerViewController:(GKMatchmakerViewController *)viewController didFindMatch:(GKMatch *)theMatch {
[self dismissModalViewControllerAnimated:YES];
self.match = theMatch;
match.delegate = self;
if (!matchStarted && match.expectedPlayerCount == 0) {
    NSLog(@"Ready to start match!");
    [self lookupPlayers];
}
}

#pragma mark GKMatchDelegate

// The match received data sent from the player.
- (void)match:(GKMatch *)theMatch didReceiveData:(NSData *)data fromPlayer:(NSString *)playerID {

if (match != theMatch) return;

[delegate match:theMatch didReceiveData:data fromPlayer:playerID];
}

// The player state changed (eg. connected or disconnected)
- (void)match:(GKMatch *)theMatch player:(NSString *)playerID didChangeState:(GKPlayerConnectionState)state {

if (match != theMatch) return;

switch (state) {
    case GKPlayerStateConnected: 
        // handle a new player connection.
        NSLog(@"Player connected!");

        if (!matchStarted && theMatch.expectedPlayerCount == 0) {
            NSLog(@"Ready to start match!");
            [self lookupPlayers];
        }

        break; 
    case GKPlayerStateDisconnected:
        // a player just disconnected. 
        NSLog(@"Player disconnected!");
        matchStarted = NO;
        [delegate matchEnded];
        break;
}                 

}

// The match was unable to connect with the player due to an error.
- (void)match:(GKMatch *)theMatch connectionWithPlayerFailed:(NSString *)playerID withError:(NSError *)error {

if (match != theMatch) return;

NSLog(@"Failed to connect to player with error: %@", error.localizedDescription);
matchStarted = NO;
[delegate matchEnded];
}

// The match was unable to be established with any players due to an error.
- (void)match:(GKMatch *)theMatch didFailWithError:(NSError *)error {

if (match != theMatch) return;

NSLog(@"Match failed with error: %@", error.localizedDescription);
matchStarted = NO;
[delegate matchEnded];
}
-(IBAction)findMatch{
   // if (![GameCenterManager isGameCenterAvailable]) return;

matchStarted = NO;
self.match = nil;

GKMatchRequest *request = [[[GKMatchRequest alloc] init] autorelease]; 
request.minPlayers = 2;     
request.maxPlayers = 2;

GKMatchmakerViewController *mmvc = 
[[[GKMatchmakerViewController alloc] initWithMatchRequest:request] autorelease];    
mmvc.matchmakerDelegate = self;

[self presentModalViewController:mmvc animated:YES];
}

#pragma mark - View lifecycle


- (void)viewDidLoad{

self.currentLeaderBoard = kLeaderboardID;

if ([GameCenterManager isGameCenterAvailable]) {

    self.gameCenterManager = [[[GameCenterManager alloc] init] autorelease];
    [self.gameCenterManager setDelegate:self];
    [self.gameCenterManager authenticateLocalUser];

    [GKMatchmaker sharedMatchmaker].inviteHandler = ^(GKInvite *acceptedInvite, NSArray *playersToInvite) {
        // Insert application-specific code here to clean up any games in progress.
        if (acceptedInvite)
        {
            GKMatchmakerViewController *mmvc = [[[GKMatchmakerViewController alloc] initWithInvite:acceptedInvite] autorelease];
            mmvc.matchmakerDelegate = self;
            [self presentModalViewController:mmvc animated:YES];

        }
        else if (playersToInvite)
        {
            GKMatchRequest *request = [[[GKMatchRequest alloc] init] autorelease];
            request.minPlayers = 2;
            request.maxPlayers = 2;
            request.playersToInvite = playersToInvite;

            GKMatchmakerViewController *mmvc = [[[GKMatchmakerViewController alloc] initWithMatchRequest:request] autorelease];
            mmvc.matchmakerDelegate = self;
            [self presentModalViewController:mmvc animated:YES];
        }
    };

}else {

    UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"Game Center Disabled"message:@"For Game Center make sure you have an account and you have a proper device connection."delegate:self cancelButtonTitle:@"Ok"otherButtonTitles:nil];
    [alert show];

}
}
4

2 に答える 2

0

招待を受け入れると、NSLog:受信した招待がコンソールに出力されますか?

[delegate invokeAccepted]メソッドは、プレーヤーが招待を受け入れたときに何が起こるかを処理する必要があります。現在どのビューが表示されているかわからないため、これはかなり面倒になることがあります。どういうわけかそれについて見つけて、ビューをプッシュする必要があります。次に、そのビューから、アプリはmatchMakerviewControllerを提示する必要があります。私の招待ブロックは次のようになります。

    [GKMatchmaker sharedMatchmaker].inviteHandler = ^(GKInvite *acceptedInvite, NSArray *playersToInvite){

        NSLog(@"Invite");

        if([AppDelegate mainMenuController].presentedViewController!=nil) {
            [[AppDelegate mainMenuController] dismissViewControllerAnimated:NO completion:^{

            }];
        }

        self.pendingInvite = acceptedInvite;
        self.pendingPlayersToInvite = playersToInvite;

        [[AppDelegate mainMenuController] presentViewController:[AppDelegate mainMenuController].multiGameMenu animated:NO completion:^{

            [[AppDelegate mainMenuController].multiGameMenu duel:nil];
        }];

    };

multiGameMenuが単なるメニューであり、duelメソッドがゲームインスタンスを作成し、findMatchWithMaxPlayers:int MinPlayers:intメソッドを呼び出す場合。どうなるか教えてください!!

于 2012-05-23T04:20:34.620 に答える
0

使ってみてください:

- (void)matchmakerViewController:(GKMatchmakerViewController *) viewController 
    didReceiveAcceptFromHostedPlayer:(NSString *)playerID
{
    [viewController setHostedPlayer:playerID connected:YES];
}

それが役立つことを願っています!

于 2012-10-31T06:32:31.583 に答える