您的位置:首页 > 移动开发 > Cocos引擎

在Cocos2dx中使用Game Center的总结

2015-07-10 02:10 489 查看
国内关于Cocos2dx中使用Game Center的教程太少了,而且都缺少很多关键步骤。

我现在使用我的切身经验来总结一下Game Center的使用技巧。

这篇文章中包含了Game Center中排行榜和成就的使用方法、一些关于OC和C++混编的问题,以及测试的技巧。

1.创建OC接口代码文件:NSCGameCenter.h和NSCGameCenter.mm,我们需要说明的是,这两个文件必须要使用Objective-C++ Source的文件类型,现在我把这两个文件的内容贴出来(内容比较多,所以折叠了):

这两个文件不要放到Cocos2dx的Resources文件夹中,因为不应该参与其它平台工程的变异。

这些代码来自于文章,并做了少许修改:http://cocos2d.9tech.cn/news/2013/1202/39024.html

NSCGameCenter.h:

#import "NSCGameCenter.h"

@implementation NSCGameCenter
@synthesize gameCenterAvailable;

//静态初始化 对外接口
static NSCGameCenter *sharedHelper = nil;
static UIViewController* currentModalViewController = nil;
+ (NSCGameCenter *) sharedGameCenter {
if (!sharedHelper) {
sharedHelper = [[NSCGameCenter 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;
} else if (![GKLocalPlayer localPlayer].isAuthenticated && userAuthenticated) {
NSLog(@"Authentication changed: player not authenticated");
userAuthenticated = FALSE;
}
}

- (void)authenticateLocalUser {
if (!gameCenterAvailable) return;
NSLog(@"Authenticating local user...");
if ([GKLocalPlayer localPlayer].authenticated == NO) {
GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
[localPlayer setAuthenticateHandler:(^(UIViewController* viewcontroller, NSError *error) {
if(localPlayer.isAuthenticated)
{
NSLog(@"LOGIN SUCCEED!");
}else{
NSLog(@"LOGIN FAILED!");
}})];

} else {
NSLog(@"Already authenticated!");
}

}

- (void) registerForAuthenticationNotification
{
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self
selector:@selector(authenticationChanged)
name:GKPlayerAuthenticationDidChangeNotificationName
object:nil];
}

//显示排行榜
- (void) showLeaderboard
{
if (!gameCenterAvailable) return;

GKLeaderboardViewController *leaderboardController = [[GKLeaderboardViewController alloc] init];
if (leaderboardController != nil) {
leaderboardController.leaderboardDelegate = self;

UIWindow *window = [[UIApplication sharedApplication] keyWindow];
currentModalViewController = [[UIViewController alloc] init];
[window addSubview:currentModalViewController.view];
[currentModalViewController presentModalViewController:leaderboardController animated:YES];
}

}

//关闭排行榜回调
- (void)leaderboardViewControllerDidFinish:(GKLeaderboardViewController *)viewController{
if(currentModalViewController !=nil){
[currentModalViewController dismissModalViewControllerAnimated:NO];
[currentModalViewController release];
[currentModalViewController.view removeFromSuperview];
currentModalViewController = nil;
}
}

//上传分数到排行榜
- (void) reportScore: (int64_t) score forCategory: (NSString*) category
{
GKScore *scoreReporter = [[[GKScore alloc] initWithCategory:category] autorelease];
scoreReporter.value = score;

[scoreReporter reportScoreWithCompletionHandler:^(NSError *error) {
if (error != nil)
{
NSLog(@"上传分数出错.");
}
else
{
NSLog(@"上传分数成功");
}
}];
}

//下载分数
- (void) retrieveTopXScores:(int)number
{
GKLeaderboard *leaderboardRequest = [[GKLeaderboard alloc] init];
if (leaderboardRequest != nil)
{
leaderboardRequest.playerScope = GKLeaderboardPlayerScopeGlobal;
leaderboardRequest.timeScope = GKLeaderboardTimeScopeAllTime;
leaderboardRequest.range = NSMakeRange(1,number);
leaderboardRequest.category = _leaderboardName;
[leaderboardRequest loadScoresWithCompletionHandler: ^(NSArray *scores, NSError *error) {
if (error != nil){
// handle the error.
NSLog(@"下载失败");
}
if (scores != nil){
// process the score information.
NSLog(@"下载成功....");
//NSArray *tempScore = [NSArray arrayWithArray:leaderboardRequest.scores];
//for (GKScore *obj in tempScore) {
//    NSLog(@"    playerID            : %@",obj.playerID);
//    NSLog(@"    category            : %@",obj.category);
//    NSLog(@"    date                : %@",obj.date);
//    NSLog(@"    formattedValue    : %@",obj.formattedValue);
//    NSLog(@"    value                : %d",obj.value);
//    NSLog(@"    rank                : %d",obj.rank);
//    NSLog(@"**************************************");
//}
}
}];
}
}

//汇报成就
//通过ID汇报成就
- (void) reportAchievement:(NSString*)id percent:(float)percent
{
if ( !gameCenterAvailable ) {
NSLog(@"ERROR: GameCenter is not available currently");
return;
}

GKAchievement* achievement = [[[GKAchievement alloc] initWithIdentifier:id] autorelease];
[self unlockAchievement:achievement percent:percent];
}

//通过成就指针汇报成就
- (void) unlockAchievement:(GKAchievement *)achievement percent:(float)percent
{
if ( achievement != nil )
{
achievement.percentComplete = percent;
achievement.showsCompletionBanner = YES;
[achievement reportAchievementWithCompletionHandler:^(NSError* error){
if ( error != nil)
{
NSLog(@"上传成就错误,错误提示为\n%@", error);
}
else
{
NSLog(@"上传成就成功\n");
[self displayAchievement:achievement];
}
}];
}
}

//显示成就
- (void) showAchievementboard
{
if (!gameCenterAvailable) return;

GKAchievementViewController *achievementController = [[GKAchievementViewController alloc] init];
if (achievementController != nil) {
achievementController.achievementDelegate = self;

UIWindow *window = [[UIApplication sharedApplication] keyWindow];
currentModalViewController = [[UIViewController alloc] init];
[window addSubview:currentModalViewController.view];
[currentModalViewController presentModalViewController:achievementController animated:YES];
}

}

//关闭成就回调
- (void)achievementViewControllerDidFinish:(GKAchievementViewController *)viewController{
if(currentModalViewController !=nil){
[currentModalViewController dismissModalViewControllerAnimated:NO];
[currentModalViewController release];
[currentModalViewController.view removeFromSuperview];
currentModalViewController = nil;
}
}

//打印某个成就
- (void) displayAchievement:(GKAchievement*)achievement
{
if ( achievement == nil) return;

NSLog(@"completed:%d", achievement.completed);
NSLog(@"lastReportDate:%@", achievement.lastReportedDate);
NSLog(@"percentComplete:%f", achievement.percentComplete);
NSLog(@"identifier:%@", achievement.identifier);
}

//加载所有成就。经测试,只能获取到已经上传过的成就状态。
- (void) loadAchievement
{
if ( self.achievementDictionary == nil )
{
self.achievementDictionary = [[NSMutableDictionary alloc] init];
}
[GKAchievement loadAchievementsWithCompletionHandler:^(NSArray* achievements, NSError* error){
if ( error == nil && achievements != nil )
{
NSArray* tempArray = [NSArray arrayWithArray:achievements];
for(GKAchievement* tempAchievement in tempArray)
{
[self.achievementDictionary setObject:tempAchievement
forKey:tempAchievement.identifier];
[self displayAchievement:tempAchievement];
}
}
}];

}

//通过成就id生成成就。首先从本地成就字典查询,查询不到则生成一个。
- (GKAchievement*) getAchievementForID: (NSString*) id
{
if ( self.achievementDictionary == nil )
{
self.achievementDictionary = [[NSMutableDictionary alloc] init];
}
GKAchievement *achievement = [self.achievementDictionary objectForKey:id];
if (achievement == nil)
{
achievement = [[[GKAchievement alloc] initWithIdentifier:id] autorelease];
[self.achievementDictionary setObject:achievement
forKey:achievement.identifier];
}
[self displayAchievement:achievement];
return [[achievement retain] autorelease];
}

//初始化所有成就状态。经测试,这段代码暂时无效。
- (void) clearAchievements
{
NSEnumerator* enumerator = [self.achievementDictionary objectEnumerator];
for(NSObject* obj in enumerator)
{
[self unlockAchievement:(GKAchievement*)obj percent:0.0];
}
}

@end


View Code
2.在AppController.mm中添加引用,并使用当前用户登陆到Game Center:

在文件开头加入以下代码:

#import "NSCGameCenter.h"


在didFinishLaunchingWithOptions中添加以下代码以登陆:

[[NSCGameCenter sharedGameCenter] authenticateLocalUser];


注意:需要特别说明的是,NSCGameCenter.h的引用,千万不能添加到头文件"*.h"中,这样会出现很多的错误,必须要添加到".mm"文件中,并且但凡要使用NSCGameCenter.h的文件都必须是Objective-C++ Source类型的,因此下面使用提交分数等操作的C++文件也必须改为Objective-C++ Source类型的文件。

3.在Cocosdx中的类文件中添加引用,并使用Game Center的相关功能

在这这一步骤中首先要做的事是修改文件类型,见上方的“注意”。

首先我们在类文件例如"sceneStarter.mm"(注意不是"sceneStarter.h")中添加:

#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
#include "NSCGameCenter.h"
#endif


此时,我们将会发现工程中出现了许多错误,例如"Reference to 'Size' is ambiguous."或者"Reference to 'Rect' is ambiguous."等等,这是因为Cocos2dx中定义的类型与Foundation中定义的类型名称相同而发生冲突,因此我们需要为这些类型加上命名空间:

//Size类型名发生冲突:
Size screenSize; //Reference to 'Size' is ambiguous.
//应该为其添加命名空间:
cocos2d::Size screenSize;


到这一步,错误都调试OK了,可以开始使用Game Center提供的功能了,我们再次仅以Leaderboard为例:

(1)打开排行榜界面:

[[NSCGameCenter sharedGameCenter] showLeaderboard];


(2)提交一个分数:

这段代码的参数需要解释的是,reportScore代表分数值,forCategory代表排行榜名称。

[[NSCGameCenter sharedGameCenter] reportScore:1000 forCategory:@"Global_Learderboard"];


代码是如此的简单,谢谢苹果带我装逼带我飞。

4.到此,代码的测试就完成了。但是我们还需要真机调试,我们需要在iPhone或iPad上进行一些简单地设置:

首先,打开"设置"->"Game Center",将"沙盒"开关打开,并重新输入密码登陆即可开始沙盒测试。

但是需要注意,仅有以"Signed Distribution Build"方式编译的App需要进行上述操作(参考Game Center Programming Guide),如果不进行该操作,将会出现以下错误:

Game Center unavailable(player is not signed in).
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: