2013-04-27 3 views
3

Я пытаюсь разработать в реальное время многопользовательской игры для IOS с помощью cocos2d, используя учебник по http://www.raywenderlich.com/3325/how-to-make-a-simple-multiplayer-game-with-game-center-tutorial-part-22Cant получить игровые центры приглашения

Все работает отлично, включая автоматическое согласование со случайным игроком, но пригласить друг не работает потому что другое устройство не может получить приглашение.

Когда я нажал кнопку приглашения друзей, а затем выбрал друга, используя стандартный интерфейс игрового центра, он говорит, что ждет (навсегда), и ничего не происходит. Мой друг не может получить приглашение от игрового центра (без уведомлений).

Я могу пригласить друга, используя функциональность близлежащих друзей (когда эта функция включена на обоих устройствах), но уведомление о приглашении не отключено.

Я потратил часы и часы на поиск в Google, нашел похожие случаи, но не решил.

Некоторые ранние отзывы о возможных ответов:

  • Я использую два устройства (один картинки и один IPad), не имитационные
  • Все настройки на ITunes подключения отлично, включая настройки многопользовательских
  • I что оба устройства подключены к песочнице с помощью разных тестовых учетных записей
  • Я уже проверял настройки уведомлений для Game Center на обоих устройствах
  • Я уже проверил все вопросы прокси/брандмауэра и примерил как Wi-Fi и Cellular для обоих устройств
  • игры приглашения включены для обоих устройств/счетов
  • Я уже проверил идентификаторы расслоением, версию приложения идентификаторы, и т.д. ...
  • Оба устройства являются IOS 6.x и приложение целевой версии ОС IOS 5.0
  • у меня нет других вопросов о игровом центре (лидеры, случайном поиск партнеров, и т.д. ... все хорошо)
  • Я вызываю метод inviteHandler, как только после того, как я аутентифицировал пользователя, как это указано в документации Apple.

Вот мой Игровой центр вспомогательный файл класса Заголовок:

#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 и он нуждается в небольшом обсуждении. Но все же вы можете заработать репутацию, отвечая на другие вопросы и задавая щедрость вашему вопросу, чтобы привлечь людей, чтобы ответить на ваш вопрос. Посмотрите [this] (http://stackoverflow.com/faq#reputation), а также [this] (http://stackoverflow.com/privileges/set-bounties) – ncm

+1

Большое спасибо за ваш комментарий ... Я проверил бы ссылку в деталях ... – emreoktem

+0

Уведомления о игровых центрах на обоих устройствах? – LearnCocos2D

ответ

0

Хорошо, кажется, что он снова работает без каких-либо изменений в наших настройках кода или сети. Я открыл билет для поддержки Apple, записи ошибок и т. Д. ... и кажется, что некоторые из них работали ...

Теперь мы понимаем, что это была ошибка в песочнице Game Center. Насколько я вижу, версия игрового центра Sanbox не такая стабильная, и люди в Apple не уделяют достаточного внимания этой услуге. Также нет способа проверить статус системы в Интернете.

Я по-прежнему продолжаю обсуждать с Apple поддержку, чтобы понять причину и поделится всем разговором здесь, когда он будет завершен.

Счастливый кодирования ...

2

Я занимаюсь с мультиплеером в течение нескольких месяцев и приглашения были реальной проблемой для меня .... и как вы, я использовал учебник Рэя, чтобы я начал , Сегодня я понял, что у кода Рэя есть ошибка, в которой приглашения не будут работать, если оба клиента имеют 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; 
           }]; 
Смежные вопросы