游戏也好,程序也好,随着用户的增加,难免会有需要增加一个在线排行的功能,这样的好处有很多,比较特别的有两点。
1. 不用考虑虚拟键盘调用后进行的用户名输入,我就是觉得做个虚拟键盘输入名字做rank让我很崩溃所以才出此“下策”
2. 即时监控用户登录情况,随着每个用户的成绩提交,可以大致知道自己的游戏有多少用户。
目前我们的选择有两个,一个是plus+ ,本来我想用它,因为我觉得plus+这个logo和颜色跟我的游戏内容比较合,奈何落花有意流水无情,我申请完等了一个星期后被他否掉 ,在这样半被迫的情况下,我选择了openfeint,并且深深为它的功能所折服,不敢专美,与各位有需要的朋友分享。
注意,我这里说的情况是在原生程序中使用openfeint,u3d的引擎的不在我的讨论之列。另外我是web程序员出身,很多描述也许不够专业和精确,请各位指出及海涵。
首先,在官网注册为开发者,建立一个项目,你会得到一个项目的client id(用于提问),一个产品编号跟一个密钥,这将放置于程序中,注意不要输错,我曾经因为少粘贴了一位密钥
结果载入程序界面老是报莫名的错误。后来还是经过Fwish版主的提醒(他也曾经遇到一样的报错),才发现问题所在。
在官网下载SDK,察看它包里的readme,注意看 Building OpenFeint With Your Project 部分
一步一步照做,注意第九步 9. You must have a prefix header. It must have the following line: #import "OpenFeintPrefix.pch"
这个是加在 项目名_Prefix.pch这个文件的最后就可以了。
一般来说,编译出4000多个错的话,多半是这里没加。另外要将所有#import到openfeint头文件的.m文件的扩展名通通改为.mm,以实现objectC和C++的混合编译。
完成以上步骤后,可以尝试编译一下,能够顺利编译就没有问题了。
接下来要做的可以在openfeint附带的sample里面看到,它的sample写得还是比较仔细的,不过它用的是UIKit和nib文件,所以开发游戏的还要根据自己的引擎做一些修改。
首先,在"项目名AppDelegate.mm"的文件里加入openfeint的载入定义部分,以让其在每次程序load完以后就起作用。
- (void) myInitOpenFeint // 初始化函数
{
// 设置信息
NSDictionary* settings = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:UIInterfaceOrientationPortrait (屏幕方向)], OpenFeintSettingDashboardOrientation,
@"你的游戏名称", OpenFeintSettingShortDisplayName,
[NSNumber numberWithBool:YES], OpenFeintSettingEnablePushNotifications,
[NSNumber numberWithBool:NO], OpenFeintSettingDisableUserGeneratedContent,
[NSNumber numberWithBool:NO], OpenFeintSettingAlwaysAskForApprovalInDebug,
window, OpenFeintSettingPresentationWindow,
nil
];
// 接口实现类
ofDelegate = [GameOFDelegate new];
ofNotificationDelegate = [GameOFNotificationDelegate new];
ofChallengeDelegate = [GameOFChallengeDelegate new];
OFDelegatesContainer* delegates = [OFDelegatesContainer containerWithOpenFeintDelegate:ofDelegate
andChallengeDelegate:ofChallengeDelegate
andNotificationDelegate:ofNotificationDelegate];
[OpenFeint initializeWithProductKey:@"这里输入key"
andSecret:@"这里输入密钥"
andDisplayName:@"Your game name"
andSettings:settings // see OpenFeintSettings.h
andDelegates:delegates]; // see OFDelegatesContainer.h
}
注释:密钥 和 key网站注册帐号后,可在后台的到
代码中ofDelegate和ofChallengeDelegate两个代理分别对应于OF的启动以及challenge模式的启动。
这两个类的具体写法可以参考sample中的例子,我基本上照抄了。
这样做完以后,可以通过执行 [OpenFeint launchDashboard]来进入OF界面,官方文档中建议这个可以作为一个按钮的绑定方法来实现。
另外重要的文档就在开发者界面里面指定功能里,点击问号会进入帮助界面,会告诉你功能相关头文件和基本的用法,注意调用方法的时候需要察看一下是否包含了带有该方法的头文件。
// 提交成绩, @"排行榜id" , 通过网站中 Leaderboards 页面,创建 一个 Leaderboards 生成
接下来我说说怎么提交成绩,很简单,就一句 [OFHighScoreService setHighScore: score forLeaderboard:@"排行榜id" onSuccess:OFDelegate() onFailure:OFDelegate()];
这个排行榜id是通过在leaderboard里面新建leaderboard取得的,在它的配置选项里成绩按照降序还是可以选择升序排列。一般都认为成绩是降序的,其实也不其然,比如我的《算术大师》,时间越短排行越高,就要按照升序排列。
至于提交成就也就一句 [OFAchievementService unlockAchievement: @"成就id" onSuccess: OFDelegate() onFailure: OFDelegate()];
这些成就可以在任何条件判断后执行,比如我指定了一个成就在成绩低于12秒的时候触发,就可以写 if(costsecond < 12) 触发成就 ,可以放心的是在你解锁了该成就以后,再次达到成就触发条件也不会重复触发成就。
备注说明:
// 成就功能就象奖状一样, 一个游戏可以设置多个成就, 比如: 当分数大于 1000时,可以设置解锁 玩家的1000分成就(得到一个1000分的奖状), 当分数大于 2000时,可以设置解锁玩家的 2000分成就(得到一个2000分的奖状)
// 下面语句为,解锁某一个成就, @"571692" 为某个成就 id , 通过网站中 Achievements 页面,创建 一个 Achievements 生成的
[OFAchievementService unlockAchievement: @"571692" onSuccess: OFDelegate() onFailure: OFDelegate()];
以上两个都是OF的基本功能,使用也相对简单,我接下来要说的是高级功能里面的challenge,我为这个折腾了两个晚上,苦于资料稀缺,无人可问,终于攻克。
challenge就是挑战功能,我的理解是它其实是一种延时对战机制,用户A在完成了指定的游戏以后,可以将游戏过程数据和结果打包传输到OF的服务器上,然后你的被挑战者从服务器上下载这些数据,以跟你同样的条件进行游戏,并且在最后跟你的游戏成绩比较,这样就完成了一次挑战的过程。大家或许也想到了,在《算术大师》里,这种机制跟游戏的相性天然吻合,我的实现是把“被挑战者下载数据以后做完题目跟挑战者比较”这个过程当成两个西部牛仔的对决,谁速度更快,谁就能够打落对方的帽子。OF的文档里提到,这个同样适用于赛车游戏的场合,挑战者的数据可以作为一辆幽灵车显示在被挑战者的画面中,可以想见,被挑战者更加不允许犯错,所以还是能够增加游戏的乐趣和对抗程度的。
下面说说代码,首先是发送挑战,这个相对简单,直接上代码吧
- (void)_sendChallenge
{
ChallengeData data;
data.score = score; //给挑战数据赋值
NSData* challengeData = [NSData dataWithBytes:(void const*)&data length:sizeof(ChallengeData)]; //这句对我来说比较深奥了,只有敬畏地照抄了
[OFChallengeService
displaySendChallengeModal:@"挑战编号"
challengeText:[NSString stringWithFormat:@"my score is %d,come on!", score]
challengeData:challengeData];
}
- (void)challenge:(id)sender{
if ([OpenFeint hasUserApprovedFeint])
{
[self _sendChallenge];
}
else
{
OFDelegate nilDelegate;
OFDelegate sendChallengeDelegate(self, @selector(_sendChallenge));
[OpenFeint presentUserFeintApprovalModal:sendChallengeDelegate deniedDelegate:nilDelegate];
}
}
千万注意!根据我的实测,挑战数据似乎是C++的变量比较不会出问题,我用NSString,NSMutableString结果在打包上传,下载解包后变成了空值,我熬的两个晚上有一个多晚上都在搞这个,结果用了C++的数组,立马就没事情了,所以,可能打包进去的数据需要类似这样的处理data.leftnum=[leftnum objectAtIndex:i] intValue];
challenge的delegate,主要是在这个函数里处理
- (void)userLaunchedChallenge:(OFChallengeToUser*)challengeToLaunch withChallengeData:(NSData*)challengeData
前面一个参数里面有挑战的名称,用户等信息,后面一个NSData里面则是完整的游戏过程数据。
这个只要按照sample里照做就可以了。设置完成后,用户在openfeint内接受挑战后将以这个delegate为入口进行后续的游戏过程处理。
最后是挑战结果处理,一般就是写个方法判断输赢平,然后设置两个回调方法
OFDelegate success(self, @selector(_submittedCompletedChallenge));
OFDelegate failure(self, @selector(_failedSubmittingCompletedChallenge));
[OFChallengeService
submitChallengeResult:challenge.resourceId
result:challenge.result
resultDescription:[NSString stringWithFormat:@"my score is %d,see you next time!", correctnum]
onSuccess:success
onFailure:failure];
我建议在_submittedCompletedChallenge不要回传数据,似乎要按照传过来的数据的格式才行,否则会出错,而回传数据只有一种情况需要用到:就是被挑战者反复尝试挑战挑战者。
challenge的适用大致就是如此了,不解的话,建议反复研究OF自带的sample,另外挑战模式的测试需要用户注册两个帐户通过在OF的界面下切换来调试,当然,一模拟器一设备是最理想的。
有一些挑战相关的数据,都是可以从它传给delegate的两个参数里取得的,比如我在游戏里设置了一个成就,就是在"little Cocoa"发出的挑战中打败little Cocoa,则能获得游戏中最大的一个成就:超越开发者,这就需要判断传过来的用户名,通过对OF的源码的研究,我以这样的方式取得了用户名:[challenge.challenge.challenger name] ,当时觉得自己很牛逼,哈哈。
以上大致就是我在使用openfeint过程中的一点心得,如果有问题的话请向我提出,如果知道的话,我会尽量解答。
另外OF其实提供了很完备的社区功能,你可以在系统里面发布公告,跟你的用户通过游戏内置的论坛进行交流,发pm给你的用户,这些原本需要复杂代码实现的功能都已经由其替你实现。所以确实能够让你的游戏从一个单机游戏进入多人游戏的世界,从何在乐趣上进步一个台阶。
最后我用一句xbox的口号结束这个教程,这也被写在了我游戏的loading页面:Game Experience may change during online play via openfeint !
阅读(2469) | 评论(0) | 转发(1) |