0

我目前正在开发 Game Center Multiplayer,但遇到了一些障碍。目前我下面的代码将验证他的用户显示媒人视图并开始一场比赛就好了。但是,当我尝试邀请朋友参加比赛时,当我接受时,要求进行比赛的警报视图会显示它会将我带到配对视图控制器并说它正在等待我另一台设备上的其他玩家它也说它正在等待让其他玩家回应。最终过了一段时间,它说邀请被取消了。我没有使用模拟器,我有 2 台设备,它们都有单独的游戏中心配置文件。一个是IOS 4.2,另一个是IOS 4.3。我不知道可能出了什么问题。我所有的多人游戏代码都在下面。此外,对于向任一设备发送数据,我很想知道一个好的网站来了解更多信息。我很高兴看到你们能想出什么。谢谢

视图控制器.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

和视图控制器.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 inviteAccepted] 方法应该处理玩家接受邀请时发生的事情。有时这会变得非常乏味,因为您不知道当前正在显示什么视图。你应该以某种方式找到它,推动观点。然后从该视图中,应用程序应该呈现 matchMaker viewController。我的邀请块如下所示:

    [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 回答