오랜만에 블로그에 포스팅을 하게 된 것 같습니다.

 

며칠 전에 Summoners와 Summoners iPhone Edition을 업데이트 후

 

도움을 많이 받은 맥부기 회원님들께 어떻게 도움이 될 방법이 없을까 고민하다가 이렇게 포스팅을 하게 되었습니다.

 

개인적으로 구글링이나 자료를 찾아가면서 한 내용이라 좀 잘못된 부분이 있을 수도 있습니다.

 

수정이 필요한 부분이 있다면 알려주시면 감사하겠습니다.

 

1. Game Center 연동하기

 

Step 1. Game Center을 연동하기 위해서는 1차로 관련 Framework이 프로젝트에 add가 되어 있어야 합니다.

 

XCode에서 자신의 project를 오픈 하신 후

 

왼쪽 편의 Frameworks 폴더에서 add->Existing Framework을 선택하신 후

iOS 4.x SDK에서

GameKit.framework을 추가해 주세요.

 

Step 2. RootViewController에 GameCenter에 필요한 Delegate를 등록합니다.

기본적으로 GameCenter에서 사용되는 matchmaking 팝업이나 LeaderBoard등의 팝업은  저 같은 경우 RootViewController위에서 구동하도록 한 관계로

RootViewController의 클래스에서 필요한 Delegate 객체를 등록하여 사용을 하였습니다.

 

RootViewController.h

#import <GameKit/GameKit.h>

@interface RootViewController:UIViewController <GKMatchmakerViewControllerDelegate, GKLeaderboardViewControllerDelegate,

GKMatchDelegate, GKAchievementViewControllerDelegate>   // 이와 같이 필요에 따라 추가를 해줍니다.

 

GKMatchmakerViewControllerDelegate : Matchmaker View를 띄울때 사용됩니다.

GKLeaderboardViewControllerDelegate : Leaderboard View를 띄울때 사용됩니다.

GKAchievementViewControllerDelegate : Achievement View를 띄울때 사용됩니다.(게임 진행 중 목표를 설정할 때 사용하는거 아시죠? ㅎㅎ)

 

우선은 GameCenter MatchMaking을 위주로 설명을 드리도록 하겠습니다.

우선 GKMatch의 객체를 생성한 다음 필요한 함수들을 미리 정의해둡니다.(이건 Apple Document에 잘 정리되어있으니 참고하셔도 될 것 같습니다.)

 

RootViewController.h

 

#import <GameKit/GameKit.h>

@interface RootViewController:UIViewController <GKMatchmakerViewControllerDelegate, GKLeaderboardViewControllerDelegate,

GKMatchDelegate, GKAchievementViewControllerDelegate>

{

GKMatch *myMatch; 

 SEL m_receiveDataCallback;
 id  m_setCallbackClass;

}

@property (nonatomic, retain) GKMatch *myMatch;

-(void)startGameCenter;

-(BOOL)isGameCenterAvailable;

-(void)authenticateLocalPlayer;

-(void)showMatchMaker;

-(void)setReceiveDataCallback:(id)callClass selector:(SEL)selector;
-(void)sendData:(NSString*)sendData;

 

 

다음은 RootViewController.m 입니다. 위에 선언된 함수들은 아래에서 하나씩 설명하도록 할게요.

RootViewController.m

 

@synthesize myMatch;

-(void)startGameCenter

{

     m_setCallbackClass = nil;

    if([self isGameCenterAvailable])   // Game Center를 사용가능한지 여부를 체크하는 함수입니다.

[self authenticateLocalPlayer];  // 사용자 인증을 하는 부분입니다. 자세한 내용은 아래에...

}

 

- (BOOL) isGameCenterAvailable
{
    // Check for presence of GKLocalPlayer API.
    Class gcClass = (NSClassFromString(@"GKLocalPlayer"));
 
    // The device must be running 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);
}

- (void) authenticateLocalPlayer // GameCenter의 User 인증 시 필요한 부분입니다.
{
    [[GKLocalPlayer localPlayer] authenticateWithCompletionHandler:^(NSError *error) {
  if (error == nil) //인증 성공 시 ...
  {
   // Insert code here to handle a successful authentication.
   NSLog(@"1--alias--.%@",[GKLocalPlayer localPlayer].alias);
   NSLog(@"2--authenticated--.%d",[GKLocalPlayer localPlayer].authenticated);
   NSLog(@"3--isFriend--.%d",[GKLocalPlayer localPlayer].isFriend);
   NSLog(@"4--playerID--.%@",[GKLocalPlayer localPlayer].playerID);
   NSLog(@"5--underage--.%d",[GKLocalPlayer localPlayer].underage);
   
   NSLog(@"Game Center: Player Authenticated!");
   
   [GKMatchmaker sharedMatchmaker].inviteHandler = ^(GKInvite *acceptedInvite, NSArray *playersToInvite){
    if(acceptedInvite){
     m_receiveDataCallback = nil;     
     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;
    }
   };
  }
  else
  {
   NSLog(@"AuthenticateLocalPlayer Error");
   // Your application can process the error parameter to report the error to the player.
  }
 }];
}

위 함수를 설명하기에 앞서 우선 전제가 있습니다.

http://itunesconnect.apple.com 에 어플이 등록이 되어 있어야 합니다.

물론 실제로 다 올릴 필요는 없고 Ready to Upload Binary 상태만 되어 있으면 됩니다.

 

그렇다는 전제 하에

위 사이트에서 Manage Your Applications를 선택 후 -> 자신의 어플을 선택합니다.

어플을 선택하시면 오른쪽 부분에 아래와 같은 메뉴가 보이실 겁니다.

오른쪽 메뉴 중에 Manage GameCenter를 선택하세요.

 

그러면 아래와 같은 메뉴가 뜰 것입니다.

지금은 MatchMaking만 테스트 할 예정이므로 다른것은 손대지 말고

Game Center Testing의 항목만 Enable로 바꿔줍시다.(저는 enable 상태이므로 현재 저렇게 Disable로 되어 있습니다.)

 

위 사이트에서 해야 할 일은 마무리 되었습니다.

 

이제 다시 프로젝트로 돌아와

Info.plist 파일을 열어 줍니다.

항목들 중 UIRequiredDeviceCapabilities 에 항목을 하나 더 add해서

gamekit을 추가 해준 다음 체크 해줍니다. (이부분 설명이 좀 빈약한가요...필요하시면 추후에 부연설명을..)

자 다시 소스로 돌아가 봅시다.

아까 설명하다 만 authenticateLocalPlayer 함수 부분을 다시 한번 보면

 

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

 

위와 같은 핸들러가 선언되어 있을 것입니다.

보통 두가지 경우가 발생을 하지요

acceptedInvite : 상대방의 초대를 받아서 수락할 경우

playersToInvite : 상대방을 초대할 경우

 

여전히 자세한 내용은 뒤로 미루고 우선 그렇다라는 것만 파악하고 진도를 나가도록 할게요.

 

authenticateLocalPlayer 이 부분까지의 구현이 마무리가 된 다음 startGameCenter를 원하는 부분에서 호출하여 실행하게되면

(아 authenticateLocalPlayer 함수에서 미구현으로 에러가 나는 부분이 있을텐데 그 부분은 우선 주석으로....

워낙 근본없는 블로거라 막 설명하네요 ㅎㅎ)

 

저 같은 경우는 startGameCenter를 XXX(프로젝트 명)AppDelegate.m 함수에서 바로 호출하였습니다.

- (void) applicationDidFinishLaunching:(UIApplication*)application
{

......

[viewController startGameCenter];

.....

}

 

저렇게 실행을 하게 되면 GameCenter에 ID가 없는 경우는 앱 실행 시에 기존 ID를 사용 할 것인지

아니면 새로운 계정을 만들 것인지 묻는 팝업이 뜨는데

그냥 새로운 계정 만들도록 합니다.(어짜피 Sandbox에 저장되는 것이니..)

 

이미 GameCenter에 로그인이 되어 있는 상태라면

아래와 같은 팝업이 보이게 됩니다.

 

이까지 나오면 GameCenter를 사용할 수 있는 상황까지 온 것이지요.

 

Step 3. MatchMaking 팝업을 띄워 봅시다.

그럼 이제 matchMaking 팝업을 띄워 보도록 합시다.

 

RootViewController.m의 아래의 함수 들을 추가하여 실행하도록 해보지요.

 

-(void)setReceiveDataCallback:(id)callClass selector:(SEL)selector
{
 m_receiveDataCallback = selector;
 m_setCallbackClass = callClass;
}

-(void)match:(GKMatch *)match didReceiveData:(NSData *)data fromPlayer:(NSString *)playerID {
 
 NSString *msg = [[[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding] autorelease];
 NSLog(@"Receive MSG : %@\n", msg);
 if(msg == nil)
  return;
 if(m_setCallbackClass !=nil)
 {
  [m_setCallbackClass performSelector: m_receiveDataCallback withObject:msg];
 }
 else
 {

   // 이 부분은 상대와 matching이 된 다음 상대에게서 메세지를 받았을 경우의 처리루틴을 넣어주시면 됩니다.
 }
}

- (void) sendData:(NSString*) sendData
{
 [myMatch sendDataToAllPlayers:[sendData dataUsingEncoding:NSASCIIStringEncoding]
      withDataMode:GKSendDataReliable error:nil];
}

 

-(void)showMatchMaker

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

 GKMatchmakerViewController *matchmakerController = [[[GKMatchmakerViewController alloc] initWithMatchRequest:request] autorelease];
 if(matchmakerController != nil)
 {
  matchmakerController.matchmakerDelegate = self;
  [self presentModalViewController: matchmakerController animated:YES];
 } 
}

 

1:1 대전이므로 player의 수는 위와 같이 최소 최대 2명으로 잡았습니다.

multi-Player를 지원하는 분들은 구미에 맞게 인원수를 조정해주시면 되겠습니다.

 

- (void)matchmakerViewControllerWasCancelled:(GKMatchmakerViewController *)viewController
{
 [self dismissModalViewControllerAnimated:YES];
 //[self.view removeFromSuperview];
 [self.view.superview removeFromSuperview];

}

- (void)matchmakerViewController:(GKMatchmakerViewController *)viewController didFailWithError:(NSError *)error
{
     [self dismissModalViewControllerAnimated:YES];
}

- (void)matchmakerViewController:(GKMatchmakerViewController *)viewController didFindMatch:(GKMatch *)match
{
 self.myMatch = match;
 if(match != nil)
  match.delegate = self;
 [self match:match player:[GKLocalPlayer localPlayer].playerID didChangeState:GKPlayerStateConnected];
 [self dismissModalViewControllerAnimated:YES];
}

- (void)match:(GKMatch *)match player:(NSString *)playerID didChangeState:(GKPlayerConnectionState)state
{
    switch (state)
    {       
  case GKPlayerStateConnected:
            NSLog(@"GAME CENTER CONNECTED");

[self sendData:@"Hello~~~"]; // 연결이 완료되었을 경우 상대에게 메세지를 테스트로 보내는 양식입니다. 입맛에 맞는데로 바꾸시면 됩니다.

   break;
   
  case GKPlayerStateDisconnected:

NSLog(@"GAME CENTER DISCONNECTED");
            // a player just disconnected.

   [self cleanUp];
   break;
    }
}

-(void)cleanUp{
 [myMatch disconnect];
 [self setReceiveDataCallback:nil selector:nil];
 myMatch.delegate = nil;
}

원하시는 부분에 버튼을 하나 만들어 위에 만들어놓은 showMatchMaker 함수를 호출하도록 합니다.

 

그 후 프로젝트를 실행시켜 그 버튼을 클릭하게 되면

 

아래와 같은 팝업이 출력이 됩니다.

 

 

팝업에 보시면 상단에 Play now라는 버튼이 있는데 이 버튼을 누르시면 자동으로

상대와 연결을 시켜주게 됩니다.

 

그 이후에 동작에 대해서는 추가로 더 포스팅을 하도록 하겠습니다.

포스팅이 길어지니 저도 정신이 없네요. -_-;;

 

아 그리고 주의 사항이 있습니다.

만약 실제로 연결을 해보고 싶으신 분은 Device에서 테스트를 하셔야 합니다.

에뮬레이터의 경우는 위 팝업까지만 뜨고 실제 연결은 되지 않습니다.

 

테스트 해보시려면 두대의 단말을 실행시켜서 하셔야 합니다.

 

혹시나 에러가 나거나 문제가 있으시면 댓글을 달아주시면 제가 추가로 부연 설명을 하도록 하겠습니다.

 

두서없이 설명하다보니 정리가 많이 미흡합니다.

 

추후에 꼭 다시 정리를 해드리도록 할게요.

 

스크랩 시에는 흔적을 남겨주시기 바랍니다.



출처 : http://blog.naver.com/PostView.nhn?blogId=bluehjh&logNo=60124995193
Posted by 오늘마감