2013-04-27 81 views
3

我试图通过使用cocos2d中通过使用http://www.raywenderlich.com/3325/how-to-make-a-simple-multiplayer-game-with-game-center-tutorial-part-22广东话接受游戏中心邀请

一切教程工作正常包括随机播放器自动匹配,但邀请朋友不起作用开发IOS的实时多人游戏因为其他设备无法收到邀请。

当我点击邀请朋友按钮,然后通过使用标准游戏中心界面选择一个朋友,它说等待(永远),没有任何反应。我的朋友无法收到游戏中心的邀请(没有通知)。

我可以通过使用附近的朋友功能(当两个设备上启用此功能时)邀请朋友,但在附近的朋友被禁用时没有邀请通知。

我花了几个小时在Google上搜索,发现类似的情况,但没有解决方案。

有关可能的答案,一些早期的反馈:

  • 我使用两个设备(一部iPhone和一部iPad),没有模拟器
  • iTunes上的所有设置连接都很好,包括多人游戏设置
  • 我验证这两个设备通过使用不同的测试帐户连接到沙箱
  • 我已经在两个设备上检查了游戏中心的通知设置
  • 我已经检查了所有的代理/防火墙问题,并试图在WiFi和蜂窝两个设备
  • 游戏邀请是为两个设备的启用/账户
  • 我已经检查过的包ID,应用版本标识等...
  • 两款器件是IOS 6.x和应用目标版本的操作系统IOS 5.0
  • 我对游戏中心没有其他问题(排行榜,随机配对,等等......无一不精)
  • 我在苹果文档中提到的尽可能验证用户身份之后尽快调用inviteHandler方法。

这里是我的游戏中心的辅助类的头文件:

#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 GCHelper : NSObject <GKMatchmakerViewControllerDelegate, GKMatchDelegate>{ 
BOOL gameCenterAvailable; 
BOOL userAuthenticated; 

UIViewController *presentingViewController; 
GKMatch *match; 
BOOL matchStarted; 
id <GCHelperDelegate> delegate; 

NSMutableDictionary *playersDict; 

GKInvite *pendingInvite; 
NSArray *pendingPlayersToInvite; 
NSMutableArray *unsentScores; 
} 

@property (retain) GKInvite *pendingInvite; 
@property (retain) NSArray *pendingPlayersToInvite; 

@property (assign, readonly) BOOL gameCenterAvailable; 

@property (retain) NSMutableDictionary *playersDict; 

@property (retain) UIViewController *presentingViewController; 
@property (retain) GKMatch *match; 
@property (assign) id <GCHelperDelegate> delegate; 

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

- (BOOL) reportAchievementIdentifier: (NSString*) identifier percentComplete: (float) percent; 

+ (GCHelper *)sharedInstance; 
- (void)authenticateLocalUser; 

@end 

这里是游戏中心辅助类

#import "GCHelper.h" 

@implementation GCHelper 

@synthesize gameCenterAvailable; 

@synthesize presentingViewController; 
@synthesize match; 
@synthesize delegate; 
@synthesize playersDict; 
@synthesize pendingInvite; 
@synthesize pendingPlayersToInvite; 

#pragma mark Initialization 

static GCHelper *sharedHelper = nil; 
+ (GCHelper *) sharedInstance { 
    if (!sharedHelper) { 
     sharedHelper = [[GCHelper alloc] init]; 
    } 
    return sharedHelper; 
} 
- (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; 
} 
- (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) { 

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

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

    } else { 

     [presentingViewController dismissModalViewControllerAnimated:NO]; 
     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; 

     [presentingViewController presentModalViewController:mmvc animated:YES]; 

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

    } 

} 

#pragma mark GKMatchmakerViewControllerDelegate 

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

// Matchmaking has failed with an error 
- (void)matchmakerViewController:(GKMatchmakerViewController *)viewController didFailWithError:(NSError *)error { 
    [presentingViewController 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 { 
    [presentingViewController 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]; 
} 

- (void)reportScore:(int64_t)score forCategory:(NSString *)category { 
    // Only execute if OS supports Game Center & player is logged in 
    if ([self isGameCenterAvailable] && [GKLocalPlayer localPlayer].authenticated == YES) 
    { 
     // Create score object 
     GKScore *scoreReporter = [[[GKScore alloc] initWithCategory:category] autorelease]; 

     // Set the score value 
     scoreReporter.value = score; 

     // Try to send 
     [scoreReporter reportScoreWithCompletionHandler:^(NSError *error) { 
      if (error != nil) 
      { 
       // Handle reporting error here by adding object to a serializable array, to be sent again later 
       [unsentScores addObject:scoreReporter]; 
      } 
     }]; 
    } 
} 

- (BOOL) reportAchievementIdentifier: (NSString*) identifier percentComplete: (float) percent { 

    if ([self isGameCenterAvailable] && [GKLocalPlayer localPlayer].authenticated == YES) 
    { 
     GKAchievement *achievement = [[[GKAchievement alloc] initWithIdentifier: identifier] autorelease]; 
     if (achievement) 
     { 
      achievement.percentComplete = percent; 
      [achievement reportAchievementWithCompletionHandler:^(NSError *error) 
      { 
       if (error != nil) 
       { 
        // Retain the achievement object and try again later (not shown). 
       } 
      }]; 
     } 

     return YES; 
    } 

    return NO; 
} 


@end 

的执行情况,最后,这是我如何从游戏层调用游戏中心(我尝试了两种不同的选项,但都没有工作)

选项1

[[GCHelper sharedInstance] findMatchWithMinPlayers:2 maxPlayers:2 viewController: [[[UIApplication sharedApplication] keyWindow] rootViewController] delegate: self]; 

选项2

AppController *app = (AppController*) [[UIApplication sharedApplication] delegate]; 
     UINavigationController *viewController = [app navController]; 
     [[GCHelper sharedInstance] findMatchWithMinPlayers:2 maxPlayers:2 viewController:viewController delegate:self]; 

任何帮助将不胜感激。在此先感谢...

+0

正如我对你question.I发现了一个明亮的锯,在回答这是不是在Q/A的一种形式,它需要一点讨论。但是,你仍然可以通过回答他人的问题来获得声望,并设置一个奖励你的问题,以吸引人们回答你的问题。[这](http://stackoverflow.com/faq#reputation),还[this](http://stackoverflow.com/privileges/set-bounties) – ncm 2013-04-27 00:59:30

+1

非常感谢您的评论...我将详细检查链接... – emreoktem 2013-04-27 01:01:52

+0

在两款设备上启用游戏中心通知? – LearnCocos2D 2013-04-27 08:44:48

回答

0

好吧,它似乎再次运行没有任何更改我们的代码或网络设置。我打开了支持Apple的支持票,bug记录等等,似乎有些人工作...

现在我们了解到这是Game Center沙箱中的一个错误。据我所知,游戏中心的sanbox版本并不稳定,苹果公司的人们对这项服务没有给予足够的重视。也无法检查互联网上的系统状态。

我仍然继续与Apple支持人员进行讨论,以便了解原因,并在完成时将此处的所有对话分享给他人。

快乐编码...

2

我一直在处理多人几个月和邀请是一个真正的问题,我....和你一样,我用雷的教程让我开始。我今天意识到,Ray的代码有一个错误,如果两个客户端都有GKMatchmakerView,那么邀请将无法工作。你需要关闭它,当你第一次收到的线沿线的东西邀请:

 [gcdelegate.viewController dismissViewControllerAnimated:YES 
           completion:^{ 
            GKMatchmakerViewController *mmvc = [[GKMatchmakerViewController alloc] initWithInvite:pendingInvite]; 
            mmvc.matchmakerDelegate = self; 
            [gcdelegate.viewController presentModalViewController:mmvc animated:YES]; 
            self.pendingInvite = nil; 
            self.pendingPlayersToInvite = nil; 
            boo_invite=true; 
           }];