cocos2d-xでGameCenter(LeaderboardとAchievement)を使う(iOSのみ)

次回行うためのメモとして。

iOSのみの実装になりますが、Androidでも別の仕組みを簡単に実装できるような考慮はしておくといいのではないかと思うので、
空のメソッドだけ用意しておくことにします。

今回使用したバージョン

  • cocos2d-2.0-x-2.0.4

実装

とりあえず基礎的な実装を行いました。

  • GameCenterへのログイン
  • GKLeaderboardViewControllerを開く
  • Leaderboardへの得点の送信
  • GKAchievementViewControllerを開く
  • Acheivementへの達成項目の送信

NativeCodeLauncherについてはCocos2d-x上からObjective-C/Javaのコードを実行する - おかひろの雑記を見てください。


GKLeaderboardViewController、GKAchievementViewControllerのDelegate実装

RootViewController.h

@interface RootViewController : UIViewController<GKLeaderboardViewControllerDelegate,GKAchievementViewControllerDelegate> {

}

RootViewController.mm

// GKLeaderboardViewControllerのDelegate
-(void)leaderboardViewControllerDidFinish:(GKLeaderboardViewController *)viewController
{
        [self dismissViewControllerAnimated:YES completion:nil];
}
// GKAchievementViewControllerのDelegate
-(void)achievementViewControllerDidFinish:(GKAchievementViewController *)viewController
{
        [self dismissViewControllerAnimated:YES completion:nil];
}

Leaderboard、Achievementを閉じたときのDelegateを実装します。


NativeCodeLauncher
cocos2d-xから呼び出すメソッドを実装します。

NativeCodeLauncher.h

namespace Cocos2dExt {
    class NativeCodeLauncher
    {
    public:
		// GameCenter
                static void loginGameCenter();
                static void openRanking();
                static void postHighScore(int kind,int score);
                static void openAchievement();
                static void postAchievement(int kind,int percentComplete);
    };
}

postHighScoreとpostAchievementの引数kindは、どの情報に値を送信するかです。
iOSのGameCenterだけであれば、文字列そのままを渡すようにしてもいいかもしれません。


NativeCodeLauncher.mm

// GameCenterにログイン
static void static_loginGameCenter()
{
        [NativeCodeLauncher loginGameCenter];
}
// Leaderboard表示
static void static_openRanking()
{
        [NativeCodeLauncher openRanking];
}
// ハイスコアを送信
static void static_postHighScore(int kind,int score)
{
        [NativeCodeLauncher postHighScore:[NSNumber numberWithInt:kind]
                                                                score:[NSNumber numberWithInt:score]];
}
// Achievement表示
static void static_openAchievement()
{
        [NativeCodeLauncher openAchievement];
}
// 達成項目を送信
static void static_postAchievement(int kind,int percentComplete)
{
        [NativeCodeLauncher postAchievement:[NSNumber numberWithInt:kind]
                                                                percent:[NSNumber numberWithInt:percentComplete]];
}

namespace Cocos2dExt
{
	// GameCenter
        void NativeCodeLauncher::loginGameCenter()
        {
                static_loginGameCenter();
        }
        void NativeCodeLauncher::openRanking()
        {
                static_openRanking();
        }
        void NativeCodeLauncher::postHighScore(int kind, int score)
        {
                static_postHighScore( kind, score);
        }
        void NativeCodeLauncher::openAchievement()
        {
                static_openAchievement();
        }
        void NativeCodeLauncher::postAchievement(int kind, int percentComplete)
        {
                static_postAchievement(kind,percentComplete);
        }
}

NativeCodeLauncher_objc.h

@interface NativeCodeLauncher : NSObject

// GameCenter
+(void)loginGameCenter;
+(void)openRanking;
+(void)postHighScore:(NSNumber *)kind score:(NSNumber *)score;
+(void)openAchievement;
+(void)postAchievement:(NSNumber *)kind percent:(NSNumber *)percentComplete;

@end

NativeCodeLauncher_objc.m

@implementation NativeCodeLauncher

// GameCenterへのログインチェック
+(void)loginGameCenter
{
        GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
        [localPlayer authenticateWithCompletionHandler:^(NSError *error) {
                if(localPlayer.authenticated)
                {
                                                
                }
                else
                {
                        
                }
        }];
}
// Leaderboardを開く
+(void)openRanking
{
        GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
        if(localPlayer.authenticated)
        {
                AppController *appController = (AppController *)[UIApplication sharedApplication].delegate;
                
                GKLeaderboardViewController *leaderboardController = [[GKLeaderboardViewController alloc]init];
                leaderboardController.timeScope = GKLeaderboardTimeScopeAllTime;
                leaderboardController.leaderboardDelegate = appController.viewController;
                
                [appController.viewController presentModalViewController:leaderboardController animated:YES];
        }
        else
        {
                NSString *alertTitle = @"";
                NSString *alertMessage = @"Game Centerへのログインが必要です。";
                UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:alertTitle message:alertMessage
                                                                                                                  delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
                [alertView show];
        }
}
// Leaderboardへの得点送信
+(void)postHighScore:(NSNumber *)kind score:(NSNumber *)score;
{
        GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
        if([localPlayer isAuthenticated])
        {
                NSString *idName = @"";
                
                switch ([kind intValue]) {
                        case 1:
                                idName = @"XXX";
                                break;
                        case 2:
                                idName = @"YYY";
                                break;
                        default:
                                break;
                }
                
                GKScore *gkScore = [[GKScore alloc]initWithCategory:idName];
                gkScore.value = [score longLongValue];
                gkScore.context = 1;
                [gkScore reportScoreWithCompletionHandler:^(NSError *error) {
                        if(error)
                        {
                                NSLog(@"Error : %@",error);
                        }
                        else
                        {
                                NSLog(@"Sent highscore.");
                        }
                }];
        }
        else
        {
                NSLog(@"Gamecenter not authenticated.");
        }
}
// Achievementを開く
+(void)openAchievement
{
        GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
        if(localPlayer.authenticated)
        {
                AppController *appController = (AppController *)[UIApplication sharedApplication].delegate;
                
                GKAchievementViewController *achievementController = [[GKAchievementViewController alloc]init];
                achievementController.achievementDelegate = appController.viewController;
                
                [appController.viewController presentModalViewController:achievementController animated:YES];
                
        }
        else
        {
                NSString *alertTitle = @"";
                NSString *alertMessage = @"Game Centerへのログインが必要です。";
                UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:alertTitle message:alertMessage
                                                                                                                  delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
                [alertView show];
        }
}
// 達成項目の達成度を送信
+(void)postAchievement:(NSNumber *)kind percent:(NSNumber *)percentComplete
{
        GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
        if([localPlayer isAuthenticated])
        {
                NSString *idName = @"";
                
                switch ([kind intValue]) {
                        case 1:
                                idName = @"XXX";
                                break;
                        case 2:
                                idName = @"YYY";
                                break;
                        default:
                                break;
                }
                
                GKAchievement *achievement = [[GKAchievement alloc] initWithIdentifier:idName];
                achievement.percentComplete = [percentComplete doubleValue];
                achievement.showsCompletionBanner = YES;
                [achievement reportAchievementWithCompletionHandler:^(NSError *error) {
                        if(error)
                        {
                                NSLog(@"Error : %@",error);
                        }
                        else
                        {
                                NSLog(@"Sent Achievement.");
                        }
                }];
        }
        else
        {
                NSLog(@"Gamecenter not authenticated.");
        }
}

@end

NativeCodeLauncher.cpp

namespace Cocos2dExt
{
	// Androidでは実装しない
	void NativeCodeLauncher::loginGameCenter()
        {
                
        }
        void NativeCodeLauncher::openRanking()
        {
                
        }
        void NativeCodeLauncher::postHighScore(int kind,int score)
        {
                
        }
        void NativeCodeLauncher::openAchievement()
        {
                
        }
        void NativeCodeLauncher::postAchievement(int kind,int percentComplete)
        {
                
        }
}

Androidはなにも動作しないようにします。
もし別のランキングの仕組みを使うような場合、ここに記述するだけで送信できます。


呼び出し
Cocos2d-Xのコードから呼び出す場合はそれぞれ1行でOKです。

// GameCenterログイン
Cocos2dExt::NativeCodeLauncher::loginGameCenter();

// Leaderboard表示
Cocos2dExt::NativeCodeLauncher::openRanking();

// Achievement表示
Cocos2dExt::NativeCodeLauncher::openAchievement();

// ハイスコア送信
Cocos2dExt::NativeCodeLauncher::postHighScore(1,1000);

// 達成項目送信
Cocos2dExt::NativeCodeLauncher::postAchievement(1, 100);