game center怎么注销挑战

居然有个小婊砸在Game Center挑战我_魔兽世界吧_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0可签7级以上的吧50个
本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:9,423,462贴子:
居然有个小婊砸在Game Center挑战我
直播应战操哭她
活久见!国外小哥因为沉...
前两天花少一帮人录完节...
芸芸重生,茫茫人海里,...
我们每个人都是富翁路上...
纵观当下娱乐圈,星二代...
了解娱乐圈实时资讯,吃...
控吧深夜趴,天下奇谈尽...
控吧深夜趴 天下奇谈尽...
导读:每天都可能遭遇...
古话说:“小时了了大未...
中国百家姓中哪些奇特的...
控吧深夜趴,天下奇谈尽...
【中建瑞通】建筑资质新办,资质增项,资质升级的好帮手
没人看我为国争光吗!
看你为国争光!
好好好看看看
这APPstore不给力下的好慢!
直播,赶紧留个名
嘛游戏。真羡慕用得起苹果的人
嘛游戏。真羡慕用得起苹果的人
青铜星玩家
百度移动游戏玩家均可认证(限百度账号),
防火隔热隔音,环保保温的彩钢夹芯板原来在这里可以找到
真他妈是慢!
话不多说撸一局先!
这是一个8级小号为你暖贴
妈哒!没人看我争光
第一把才1000分
感觉和2048差不多
没人理我去洗澡了回来再撸
要多少流量啊~
楼主加油!操翻对面的资本主义基佬为国争光
这个我发现每个人都会收到来自国外的挑战,我怀疑是APPstore搞的推广让人去下游戏
小婊砸还敢挑战我
贴吧热议榜
使用签名档&&
保存至快速回贴推荐到广播
610046 人聚集在这个小组
(周渝民前妻)
(破坏大王)
第三方登录:1097人阅读
GameCenter
你也许曾听说过Game Center,它是自打iOS 4.1被引入的在线多人社交游戏网络,支持玩家邀请好友一起玩儿游戏,还可以建立一个多人游戏的会话,追踪成就系统,以及其他功能。
除了可以让开发者更轻松的实现一些基本功能外,它还改善了另一个基础问题:app推广。如今App Store上有超过1百万款app,单个用户发现你的app的概率将会非常低。Game Center通过好友系统改善了此类问题,你可以查看你的好友都在玩儿些什么游戏,因此你的游戏的曝光率被增加了。
iOS 6.0为Game Center引入了一系列新的API,它们不仅可以增加你的游戏曝光率,而且还能增加用户粘性。其中一项功能是挑战好友,即使你的Gamecenter好 友们没有安装此游戏,也可以邀请向他们发送挑战。例如,一个玩家在你的游戏里得到了高分,他可以向他的朋友发送一个挑战邀请并且说:“嘿,来试试赢我 啊!”
当朋友接收到挑战后,会立即看到消息中你的游戏的链接。不难想象这一特性能够成倍的增加用户留存率!由于考虑到Game Center上庞大的用户群体,这一点足够说明你应该在游戏中添加挑战功能。
使用挑战之前要先使用Game Center,所以本篇教程将首先带你整体过一遍Game Center,包括设置Game Center并添加一个简单的排行榜,同时会在过程中指出iOS 6新增的内容。
注意:&本篇教程要求你熟悉Cocos2D并且基于它制作过游戏。如果你是Cocos2D的新手,可以先在本网站学习。
跳跃猴游戏
首先下载&–
MonkeyJump(跳跃猴)是一个简单的横向卷轴游戏,它由我最喜欢的游戏引擎Cocos2D制作的。它是基于一个由Cocos2D学习工作室制作的叫做CatJump的游戏。我向其中加了一些有趣的元素,另外为游戏制作了新的美术资源。
游戏中的主要角色很明显,是一只猴子,游戏的主要目标让猴子达到最远的距离同时躲避敌人。
MonkeyJump非常容易上手,即使是你的妈妈也能玩儿!只需要轻点屏幕就可以让猴子跳过敌人了。游戏会记录猴子跑的距离并以此为玩家打分。
亲自是玩儿一下吧!把starter项目解压,在Xcode中编译并运行。试试看你能跑多远!:]
另外简单过一遍代码,看看这些层和场景之间是如何协调工作的。
配置Game Center
在做任何有关Game Center Challenges功能之前,首先要做的就是配置你的app使用Game Center!这个过程需要三个步骤:
创建并设置App ID。
在iTunes Coonect上注册你的app。
启用Game Center的功能,比如leaderboards(排行榜)
让我们按顺序过一遍这些步骤。对于许多有Game Center经验的读者来说,这会是相当熟悉的,但我保证我会很快的讲完这一部分。
创建并设置APP ID
第一步,你需要创建一个App ID。登录到iOS Dev Center,选择iOS Provisioning Portal。
在Provisioning Portal中,选择App IDs,选择create a new App ID。使用monkeyjump作为游戏名字并输入一个bundle identifier,通常这里使用倒转的DNS命名,比如com.ali.MonkeyJump(如果你没有自己的域名,你可以使用你自己的名字代 替)。
当你完成后,点击Submit按钮。打开MonkeyJump Xcode工程,选择project root,然后选择MonkeyJump target,在Summary tab中把Bundle Identifier替换为你刚刚在Provisioning Portal中创建的那个。
编译并运行,在真机上运行试试看。如果一切配置都正确的话,游戏应该立刻启动。如果没有,那么clean一下项目并重新编译一次。
在ITUNES CONNECT中注册你的APP
接下来的步骤是iTunes Connect中创建一个新app。首先登录到iTunes Connect,切换到application management子页面,点击位于左上角的Add New App按钮。(如果你同时拥有Mac和iOS的开发者帐号,你可能需要选择app的类型 – 当然要选择iOS)。
在第一个屏幕中,输入MonkeyJump作为游戏名字,400作为SKU number(SKU number可以是任意的数字/单词,你也可以设置成你想要的)并选择上一步中创建的Bundle Identifier。
当你输入完所有值后,点击Continue。在弹出的提示框中输入所有需要的信息。因为你只需要在本教程中使用此项目,所以一切从简,只填入强制要求填入的项目。?
你需要上传一个大的app icon 和一个截图。为了让过程更容易,我为你准备好了。你可以解压这个ZIP文件,使用里边的图片来很快的完成这个烦人的注册过程。
当你完成后,点击Save按钮,如果一切都OK的话,你会得到以下提示:
欢呼!你已经在iTunes Connect中注册了你的app并完成了最敷衍了事的部分,哈哈。接下来还需要几个小步骤来激活Game Center。不要慌张,因为最麻烦的部分已经过去了。?
启用GAME CENTER的功能
点击蓝色的Manage Game Center按钮并点击Enable for Single Game Button。太棒了!你已经为你的游戏启用了Game Center了。这个步骤简单到只需要点击按钮 – 不过别高兴的太早,之后你还是需要写很多的代码才行哦。:]
你还没有完成本部分,还要添加一个leaderboard(排行榜)才算完。你可能会问这篇教程不是讲challenges的吗,跟leaderboard有什么关系呢,别急,稍后你就明白了!
使用challenge要求添加一个leaderboard。点击Add Leaderboard按钮并选择Single Leaderboard类型。之后你会看到一个如下的表格:
在leaderboard reference name栏输入High Scores,leaderboard ID栏输入HighScores。
注意:&一般来说,我推荐你使用包名字的扩展作为leaderboard或者achievement(成就)的ID。例如,以上的名字就是 com.ali.MonkeyJump.HighScores(你需要把com.ali替换为你自己的)。但是为了本篇教学的简化,直接把它命名为 HighScores(而不是加上域名的前缀)。
把Sort Order设置为High to Low,Score Format Type设置为Integer。最后,点击Add Language按钮。为language details添入以下内容:
此处添加图片不是虽然强制的,但是添加它是个很好的实践机会。这里你需要使用的资源是iTunes resource文件夹中名字为icon_leaderboard_512.png,把它用作高分排行榜的icon。当你完成后,点击Save。
最后,点击Done按钮。到这里,一个leaderboard的配置就完成了,以后如果你想添加更多的,你就可以随心所欲了。
验证本地玩家
在你开始写代码之前,你需要首先import(导入)GameKit framework。在 Xcode 4.5 中打开MonkeyJump工程并进入target设置。打开Build Phases子页面,选择Link Binary With Libraries部分。点击 “+” 按钮,选择导入GameKit framework到工程中。
接下来你需要写一些代码来验证用户。注意如果你不验证用户,你是不能够使用任何Game Center提供的很棒的功能的。
这里的Player代表当前正在玩儿你的游戏玩家。在Game Center的术语里,这由GKLocalPlayer表示。
验证过程简单的分为两个步骤:
首先你调用一个authenticate call 到 Game Center平台。
平台会异步的处理你的请求,结束后会调用一个回调函数。如果玩家已经登录了(95%的情况),一个欢迎的横幅会弹出来,如果玩家没登录,那么一个允许玩家注册的登录界面会弹出来。
我们这就写些代码。这里我们使用一个单例模式,也就是说所有的Game Center的代码都在一个类中。
在Xcode中,右键点击MonkeyJump group,选择New Group。把新group命名为GameKitFiles。然后,右键点击新创建的这个group并选择New File…,文件模版选择Objective-C Class template。把文件命名为GameKitHelper,同时继承NSObject。
把GameKitHelper.h中的内容替换为以下内容:
Include the GameKit framework
#import &GameKit/GameKit.h&
Protocol to notify external
objects when Game Center events occur or
when Game Center async tasks are completed
@protocol GameKitHelperProtocol&NSObject&
@interface GameKitHelper :
@property (nonatomic, assign)
id&GameKitHelperProtocol&
// This property holds the last known error
// that occured while using the Game Center API's
@property (nonatomic, readonly) * lastE
+ (id) sharedGameKitH
// Player authentication, info
-(void) authenticateLocalP
以上代码自说明性很强并且有很详细的注释。你在此所做的无非就是声明两个方法和两个属性,其中一个属性是delegate,另外一个会记录下最近一次使用GameKit framework报出的错误。
切换到GameKitHelper.m并把文件替换为以下内容:
#import &GameKitHelper.h&
#import &GameConstants.h&
@interface GameKitHelper ()
&GKGameCenterControllerDelegate& {
BOOL _gameCenterFeaturesE
@implementation GameKitHelper
#pragma mark Singleton stuff
+(id) sharedGameKitHelper {
static GameKitHelper *sharedGameKitH
static dispatch_once_t onceT
dispatch_once(&onceToken, ^{
sharedGameKitHelper =
[[GameKitHelper alloc] init];
return sharedGameKitH
#pragma mark Player Authentication
-(void) authenticateLocalPlayer {
GKLocalPlayer* localPlayer =
[GKLocalPlayer localPlayer];
localPlayer.authenticateHandler =
^(UIViewController *viewController,
[self setLastError:error];
if ([CCDirector sharedDirector].isPaused)
[[CCDirector sharedDirector] resume];
if (localPlayer.authenticated) {
_gameCenterFeaturesEnabled = YES;
} else if(viewController) {
[[CCDirector sharedDirector] pause];
[self presentViewController:viewController];
_gameCenterFeaturesEnabled = NO;
这里你声明了一个名为_gameCenterFeaturesEnabled的变量。这个BOOL类型的变量会标识验证是否成功。
iOS 6.0中验证玩家的方式有所改变。所有你需要的就是设置GKLocalPlayer对象的authenticationHandler属性,正如你在authenticateLocalPlayer方法中看到的。authenticationHandler block有两个参数,它是被Game
Center平台自动调用的。
这个block被系统在以下情形中被调用:
当你设置了authenticationHandler并发出了验证玩家的请求。
当app进入foreground(前台)。
在登录时,例如玩家在进入游戏前没有登录,进入时会弹出登录界面,在这个界面中的任何交互都会调用authenticationHandler。
authenticationHandler有两个参数:
第一个是&UIViewController&,它代表如果你未登录Game Center,需要你弹出的登录view controller。
还有一个&NSError&表示验证过程中发生的任何错误。
值得注意的是,在这个block中,你首先检查玩家是否验证过了,如果玩家已经被验证了,你需要做的就是把_gameCenterEnabled变量置为true,然后就可以继续游戏了。
如果login view controller(authenticationHandler block中的第一个参数)不为nil,就意味着玩家还没有登录Game Center。如果是这种情况,你先暂停游戏,然后为玩家弹出登录的view controller。如果玩家在此界面登录成功或者点击Cancel按钮,以上那个handler block还会被调用一次。
在老版本的Game Center中,开发者是没法决定何时为玩家弹出登录界面的。这个新方法给予了开发者更多可控性,来决定在何时弹出此界面。
最终,如果验证失败了,你需要恰当的禁用所有Game Center的功能。这里通过把_gameCenterFeaturesEnabled变量置为false来让app无视Game Center的功能调用。
为了让authenticateLocalPlayer起作用,你还需要一些代码。在GameKitHelper.m中加入以下内容:
#pragma mark Property setters
-(void) setLastError:(*)error {
_lastError = [error copy];
if (_lastError) {
NSLog(@&GameKitHelper ERROR: %@&, [[_lastError userInfo]
description]);
#pragma mark UIViewController stuff
-(UIViewController*) getRootViewController {
return [UIApplication
sharedApplication].keyWindow.rootViewC
-(void)presentViewController:(UIViewController*)vc {
UIViewController* rootVC = [self getRootViewController];
[rootVC presentViewController:vc animated:YES
completion:nil];
以上代码实现了authenticateLocalPlayer需要的三个函数:
lastError属性被声明为readonly。因此你不能在直接设置它的值,需要手动为其添加一个setter方法。这就是setLastError:的作用。
Game Center登录controller需要真实显示出来,这样玩家才能做登录操作。presentViewController: 和 getRootViewController方法负责得到root view controller并且通过root view controller把登录界面显示出来。
太棒了!现在是时候测试一下GameKitHelper了。打开Prefix.pch并加入必要的import:
#import &GameKitHelper.h&
接下来,打开MenuLayer.m并在onEnter(紧跟在[super onEnter]语句之后)中加入如下内容。每当主界面显示的时候都会验证玩家。
[[GameKitHelper sharedGameKitHelper]
authenticateLocalPlayer];
编译并运行。当主菜单显示出来的时候你会看到以下的内容:
左边的图示演示了登录view controller(玩家未登录Game Center的情况)。右边的演示了welcome banner,每当验证成功时就会弹出。
注意:&为了测试验证过程,首先登出Game Center然后再在MonkeyJump app里登录。只有这样才能在沙盒模式下运行Game Center。另外,在模拟器上运行也许行不通(至少在写这篇教程时还不行)。你需要在真机上进行测试。
提交分数到Game Center
若提交一个分数到Game Center,需要使用GKScore类。这个类保存着有关玩家分数和分数所属类别的信息。
类别指的是leaderboard ID。例如,你希望提交一个分数到High Scores排行榜,那么GKScore对象的category就应该是你在iTues Connect设置的那个leaderboard ID,这里就是HighScores。
打开GameKitHelper.h并加入以下方法声明:
-(void) submitScore:(int64_t)score
category:(*)
接下来,在GameKitHelperProtocol中加入以下方法声明:
-(void) onScoresSubmitted:(bool)
打开GameKitHelper.m并加入以下代码:
-(void) submitScore:(int64_t)score
category:(*)category {
//1: Check if Game Center
features are enabled
if (!_gameCenterFeaturesEnabled) {
CCLOG(@&Player not authenticated&);
//2: Create a GKScore object
GKScore* gkScore =
[[GKScore alloc]
initWithCategory:category];
//3: Set the score value
gkScore.value =
//4: Send the score to Game Center
[gkScore reportScoreWithCompletionHandler:
^(* error) {
[self setLastError:error];
BOOL success = (error == nil);
if ([_delegate
respondsToSelector:
@selector(onScoresSubmitted:)]) {
[_delegate onScoresSubmitted:success];
以下是上面方法的分步说明:
检查Game Center功能是否启用了,只有当启用时再执行之后的代码。
创建一个GKScore的实例。GKScore所需要的分数所属类别作为init方法的参数传入。
设置GKScore的分数值。
使用reportScoreWithCompletionHandler:方法把GKScore对象发送到Game Center端。当分数被发送后,平台会调用completion handler。completion handler是一个只有一个参数的block,在这里是一个NSError
对象,你可以通过它来查看分数是否发送成功了。
现在你已经有了发送分数到Game Center的方法了,是时候使用它了。在使用该方法之前,打开GameConstants.h并在文件末尾(但在最后的#endif之前)加入以下define语句:
#define kHighScoreLeaderboardCategory @&HighScores&
然后,打开GameLayer.m并找到monkeyDead方法。根据此方法的名字透露的信息,这个方法是在猴子挂掉时调用的。换句话说,就是游戏结束的时候。
在该方法的开头加入以下语句:
[[GameKitHelper sharedGameKitHelper]
submitScore:(int64_t)_distance
category:kHighScoreLeaderboardCategory];
编译并运行。玩儿一遍游戏直到猴子挂掉。可怜的小家伙!
当你玩儿完后,你的分数会被发送到Game Center。为了验证是否真的发送成功了,打开Game Center app,点击Games分页并选择MonkeyJump。这里的排行榜会显示你的分数。下边是HighScores排行榜的截图示例:
你打败我的分数了吗?不要使用改代码的作弊手段哦!:]
Game Center 挑战
终于到了你期待已久的部分了!
Game Center 挑战是iOS 6.0 的 Game Center中引入的最大的功能。挑战可以让你的游戏病毒式地传播,而且还可以极大的增加玩家的留存。
但是问题是,使用挑战功能是一件异常艰难并且复杂的工作,因为它有着数量广袤的的API而且非常复杂(作者开玩笑说的)。
只是开个玩笑啦!把挑战功能集成到你的游戏中,所有要做的仅仅是…完全不需要任何工作!?如果你的游戏支持leaderboards或者achievements,那么你的游戏就会自动的支持challenges(挑战),而不需要做任何额外的工作。
为了测试这个,打开Game Center程序(确保你是在沙盒模式下)。进入Games分页并打开MonkeyJump游戏。
如果你已经玩儿了有几次游戏,从leaderboard中选择你的高分。你会看到在一个Challenge Friends的按钮出现在详细信息界面。点击它,输入想要挑战的好友的名字,点击Send。当challenge被成功发送后,你的好友会收到一个 push notification。
注意:&为了测试challenges,你需要两台运行iOS 6.0的设备,每台都需要登入不同的Game Center帐号,并且互相之间要加为好友。
Challenges绝不仅仅是push notifications而已。让我通过一个例子来详细地为你说明它。
假如我给Ray发送了一个500米成绩的挑战。Ray会在他的设备上接收到一个通知他此挑战的push notification。我们假设Ray在回应挑战的游戏中得到了1000米的成绩。也就是说Ray挑战成功了。那么他当然想让我知道这件事儿。
由于游戏是把所有分数发送到Game Center上的,Game Center自动地获取到Ray挑战成功了,所以它会同时发送一个挑战完成的push notification到两个人的设备上去。Ray之后还可以以1000米这个分数向我发起挑战。他一定不知道我再梦里也能跑1000米吧。
这个过程可以无穷尽的持续下去,每一次一方都会超过另一方的分数。这样就会让人很上瘾,这种自我延续的特性使得每个游戏开发者都应该在他/她的游戏中集成challenge。
到现在为止,你已经在Game Center应用中测试了challenge,但是怎么样才能允许玩家在游戏内也能想他/她的好友发起挑战呢?
这就是接下来要做的。:]你将要在你的游戏中添加一个朋友选择器,允许玩家选择他/她的好友,并发送挑战。
打开GameKitHelper.h并加入一个新的属性。
@property (nonatomic, readwrite)
BOOL includeLocalPlayerS
接下来在GameKitHelperProtocol加入以下方法声明:
-(void) onScoresOfFriendsToChallengeListReceived:
-(void) onPlayerInfoReceived:
同时在GameKitHelper中加入以下方法声明:
-(void) findScoresOfFriendsToC
-(void) getPlayerInfo:(*)playerL
-(void) sendScoreChallengeToPlayers:
(*)players
withScore:(int64_t)score
message:(*)
然后在GameKitHelper.m中定义以上的方法。让我们从findScoresOfFriendsToChallenge开始。添加以下内容:
-(void) findScoresOfFriendsToChallenge {
GKLeaderboard *leaderboard =
[[GKLeaderboard alloc] init];
leaderboard.category =
kHighScoreLeaderboardC
leaderboard.playerScope =
GKLeaderboardPlayerScopeFriendsO
leaderboard.range = NSMakeRange(1, 100);
[leaderboard
loadScoresWithCompletionHandler:
^( *scores,
[self setLastError:error];
BOOL success = (error == nil);
if (success) {
if (!_includeLocalPlayerScore) {
*friendsScores =
for (GKScore *score in scores) {
if (![score.playerID
isEqualToString:
[GKLocalPlayer localPlayer]
.playerID]) {
[friendsScores addObject:score];
scores = friendsS
if ([_delegate
respondsToSelector:
(onScoresOfFriendsToChallengeListReceived:)]) {
[_delegate
onScoresOfFriendsToChallengeListReceived:scores];
这个方法负责获取玩家的所有好友的分数。通过查询HighScores leaderboard获取玩家的好友分数。
每次你查询分数,Game Center都会默认添加本地玩家的分数进去。例如上边的方法,当你获取所有好友的分数的同时,Game Center返回的数组不但包含所有玩家好友的,也会包含玩家自身的分数。所以这里你使用了includeLocalPlayerScore属性来决定是 否要添加玩家自己的分数到返回结果中,默认的这个值是NO(不包含玩家的分数)。
现在添加以下方法:
-(void) getPlayerInfo:(*)playerList {
if (_gameCenterFeaturesEnabled == NO)
if ([playerList count] & 0) {
loadPlayersForIdentifiers:
playerList
withCompletionHandler:
^(* players, * error) {
[self setLastError:error];
if ([_delegate
respondsToSelector:
@selector(onPlayerInfoReceived:)]) {
[_delegate onPlayerInfoReceived:players];
此方法通过传入一个玩家ID的数组来获得这些玩家的信息。
还有最后一个方法 – 添加以下代码:
-(void) sendScoreChallengeToPlayers:
(*)players
withScore:(int64_t)score
message:(*)message {
GKScore *gkScore =
[[GKScore alloc]
initWithCategory:
kHighScoreLeaderboardCategory];
gkScore.value =
[gkScore issueChallengeToPlayers:
players message:message];
此方法向一组玩家发送一个分数挑战,同时还跟随着一条玩家发送的消息。
很好!接下来,你需要一个friend picker(玩家选择器)。friend picker将会允许玩家输入一条自定义的消息并选择他/她想要发送挑战的玩家们。默认情况下,它会选择那些当前分数比你低的玩家,因为这些人玩家理所应 当向他们发送挑战。毕竟每个玩家都希望赢!?
在Xcode中新建一个group并命名为ViewControllers。然后新建一个继承自UIViewController的文件并将其命名为FriendsPickerViewController。注意这里要选中“With XIB for user interface”。如下所示:
打开FriendsPickerViewController.xib文件,设置view’s orientation为landscape,拖拽进来一个UITableView,一个UITextField和一个UILabel到canvas中,设置label的text属性为“Challenge
message”。
另外,为了让次界面看起来和游戏的其他界面相吻合,添加bg_menu.png作为背景图片。最终的view controller看起来如下图所示:
打开FriendsPickerViewController.h并在@interface添加如下语句:
typedef void
(^FriendsPickerCancelButtonPressed)();
typedef void
(^FriendsPickerChallengeButtonPressed)();
这两个新的数据类型,FriendsPickerCancelButtonPressed 和 FriendsPickerChallengeButtonPressed,是你将要使用的两种block。block类似C函数,它有返回类型(这里是 void)和零个或多个参数。typedef定义使之后在代码中使用此block更为简化。
添加如下属性到@interface部分:
@property (nonatomic, copy)
FriendsPickerCancelButtonPressed
cancelButtonPressedB
@property (nonatomic, copy)
FriendsPickerChallengeButtonPressed
challengeButtonPressedB
这些属性是将来Cancel或者Challenge按钮按下时所执行的block。
接下来添加Cancel和Challenge按钮到view controller中。打开FriendsPickerViewController.m并替换viewDidLoad为以下代码:
- (void)viewDidLoad {
[super viewDidLoad];
UIBarButtonItem *cancelButton =
[[UIBarButtonItem alloc]
initWithTitle:@&Cancel&
style:UIBarButtonItemStylePlain
target:self
action:@selector(cancelButtonPressed:)];
UIBarButtonItem *challengeButton =
[[UIBarButtonItem alloc]
initWithTitle:@&Challenge&
style:UIBarButtonItemStylePlain
target:self
action:@selector(challengeButtonPressed:)];
self.navigationItem.leftBarButtonItem =
self.navigationItem.rightBarButtonItem =
challengeB
此方法添加了两个UIBarButtonItems到view controller中,分别是Cancel和Challenge按钮。现在添加当这两个按钮被按下时所触发的方法。
- (void)cancelButtonPressed:(id) sender {
if (self.cancelButtonPressedBlock != nil) {
self.cancelButtonPressedBlock();
- (void)challengeButtonPressed:(id) sender {
if (self.challengeButtonPressedBlock) {
self.challengeButtonPressedBlock();
上边的方法很好理解,你所做的就是在函数中执行challenge和cancel的block。
在你把此view controller集成到游戏中并验证一切正常之前,你需要先写一个初始化方法来获取本地玩家的分数。在完成这一步之前,你先要定义一个变量存储此分数。
在FriendsPickerViewController.m中的类extension块儿中添加以下变量 – 记得要在变量之间插入花括号,最终的类extension看起来如下所示:
@interface FriendsPickerViewController () {
现在添加如下的初始化方法:
- (id)initWithScore:(int64_t) score {
self = [super
initWithNibName:
@&FriendsPickerViewController&
bundle:nil];
if (self) {
在FriendsPickerViewController.h中添加该方法声明,如下所示:
-(id)initWithScore:(int64_t)
现在你就可以测试以下此view controller了,看看它是不是如预期一样工作正常。打开GameKitHelper.h并定义一个如下方法:
showFriendsPickerViewControllerForScore:
然后打开GameKitHelper.m并添加如下import语句:
#import &FriendsPickerViewController.h&
然后,添加如下方法:
showFriendsPickerViewControllerForScore:
(int64_t)score {
FriendsPickerViewController
*friendsPickerViewController =
[[FriendsPickerViewController alloc]
initWithScore:score];
friendsPickerViewController.
cancelButtonPressedBlock = ^() {
[self dismissModalViewController];
friendsPickerViewController.
challengeButtonPressedBlock = ^() {
[self dismissModalViewController];
UINavigationController *navigationController =
[[UINavigationController alloc]
initWithRootViewController:
friendsPickerViewController];
[self presentViewController:navigationController];
此方法会模态地弹出FriendPickerController。它还定义了当Challeng和Cancel按钮被按下时触发的block。目前它们只是简单的使该界面消失。
打开GameOverLayer.m并把menuButtonPressed:中的CCLOG(@”Challenge button pressed”);行替换为以下内容:
[[GameKitHelper sharedGameKitHelper]
showFriendsPickerViewControllerForScore:_score];
到了关键时刻了!编译并运行,玩儿一局MonkeyJump,在game over屏点击Challenge Friends按钮,你会看到FriendsPickerViewController弹出来了。如果你点击不论Challenge还是Cancel按钮 都会使该界面消失。
很好!你的游戏现在有了好友选择的界面了。但是这个界面还没显示任何的好友,这样是不行的。
没必要感觉孤单,我们这就加入此功能!
打开FriendsPickerViewController.m并把类extension替换为以下内容:
@interface FriendsPickerViewController ()
&UITableViewDataSource,
UITableViewDelegate,
UITextFieldDelegate,
GameKitHelperProtocol& {
@property (nonatomic, weak)
IBOutlet UITableView *tableV
@property (nonatomic, weak)
IBOutlet UITextField *challengeTextF
注意这里的interface部分实现了很多的protocol。同时,它还有两个IBOutlet,一个是UITableView的,另一个是UITextfield的。使用Interface Builder把它们和相应的view关联起来,如下所示:
接下来设置UITableView的delegate和data source,还有UITextField的delegate,在Interface Builder中把它们都设置为File’s Owner。
为了完成这个,首先选择UITableView,在Connections inspector中,把data source和delegate outlet分别拖拽到左侧的File’s Owner,如下图所示:
为UITextField重复此步骤。
切换到FriendsPickerViewController.m并在initWithScore:方法的if语句中的_score =行之后添加如下代码:
dataSource = [ dictionary];
GameKitHelper *gameKitHelper = [GameKitHelper sharedGameKitHelper];
gameKitHelper.delegate =
[gameKitHelper findScoresOfFriendsToChallenge];
此方法初始化了data source,设置其自身为GameKitHelper的delegate并调用findScoresOfFriendsToChallenge。如果你 还记得,这个方法是用来获取本地玩家所有好友的分数的。接下来需要实现 onScoresOfFriendsToChallengeListReceived:代理方法,来处理当玩家的分数获取到后的事件:
onScoresOfFriendsToChallengeListReceived:
(*) scores {
*playerIds =
[scores enumerateObjectsUsingBlock:
^(id obj, NSUInteger idx, BOOL *stop){
GKScore *score = (GKScore*)
if(_dataSource[score.playerID]
_dataSource[score.playerID] =
[ dictionary];
[playerIds addObject:score.playerID];
if (score.value & _score) {
[_dataSource[score.playerID]
setObject:[ numberWithBool:YES]
forKey:kIsChallengedKey];
[_dataSource[score.playerID]
setObject:score forKey:kScoreKey];
[[GameKitHelper sharedGameKitHelper]
getPlayerInfo:playerIds];
[self.tableView reloadData];
以上代码有很强的自说明性,不过还是按步骤解释一下:
创建一个名为playerIds的数组用来存储本地玩家所有好友的ID。
然后此方法开始遍历返回的分数。
对每一个分数,都在data source中创建相应的数据,并且在playerIds数组中保存player ID。
如果这个分数比本地玩家的分数低,该分数对应的在data source中的数据会被标记。
分数被保存在data source字典中。
GameKitHelper的getPlayerInfo:方法调用时使用playerIds数组作为参数。该方法会返回每个好友的详细信息,比如好友的名字和头像。
以上代码需要一些#define语句才能正常工作,在文件头#import行之后,加入以下内容(有些是以后会用到的):
#define kPlayerKey @&player&
#define kScoreKey @&score&
#define kIsChallengedKey @&isChallenged&
#define kCheckMarkTag 4
然后你需要实现onPlayerInfoReceived:代理方法。这个方法会在本地玩家所有好友的信息获取到之后调用。
-(void) onPlayerInfoReceived:(*)players {
enumerateObjectsUsingBlock:
^(id obj, NSUInteger idx, BOOL *stop) {
GKPlayer *player = (GKPlayer*)
if (_dataSource[player.playerID]
_dataSource[player.playerID] =
[ dictionary];
[_dataSource[player.playerID]
setObject:player forKey:kPlayerKey];
[self.tableView reloadData];
这个方法也非常直接了当,因为你有每个玩家的详细信息,你只需要更新每个玩家的_dataSource字典即可。
_dataSource字典用来作为table view的数据源。接下来实现table view的data source方法,如下所示:
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section {
return _dataSource.
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:( *)indexPath {
*CellIdentifier = @&Cell identifier&;
static int ScoreLabelTag = 1;
static int PlayerImageTag = 2;
static int PlayerNameTag = 3;
UITableViewCell *tableViewCell =
[tableView
dequeueReusableCellWithIdentifier:
CellIdentifier];
if (!tableViewCell) {
tableViewCell =
[[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
tableViewCell.selectionStyle =
UITableViewCellSelectionStyleG
tableViewCell.textLabel.textColor =
[UIColor whiteColor];
UILabel *playerName =
[[UILabel alloc] initWithFrame:
CGRectMake(50, 0, 150, 44)];
playerName.tag = PlayerNameT
playerName.font = [UIFont systemFontOfSize:18];
playerName.backgroundColor =
[UIColor clearColor];
playerName.textAlignment =
UIControlContentVerticalAlignmentC
[tableViewCell addSubview:playerName];
UIImageView *playerImage =
[[UIImageView alloc]
initWithFrame:CGRectMake(0, 0, 44, 44)];
playerImage.tag = PlayerImageT
[tableViewCell addSubview:playerImage];
UILabel *scoreLabel =
[[UILabel alloc]
initWithFrame:
CGRectMake(395, 0, 30,
tableViewCell.frame.size.height)];
scoreLabel.tag = ScoreLabelT
scoreLabel.backgroundColor =
[UIColor clearColor];
scoreLabel.textColor =
[UIColor whiteColor];
[tableViewCell.contentView
addSubview:scoreLabel];
UIImageView *checkmark =
[[UIImageView alloc]
initWithImage:[UIImage
imageNamed:@&checkmark.png&]];
checkmark.tag = kCheckMarkT
checkmark.hidden = YES;
CGRect frame = checkmark.
frame.origin =
CGPointMake(tableView.frame.size.width - 16, 13);
checkmark.frame =
[tableViewCell.contentView
addSubview:checkmark];
[_dataSource allValues][indexPath.row];
GKScore *score = dict[kScoreKey];
GKPlayer *player = dict[kPlayerKey];
*number = dict[kIsChallengedKey];
UIImageView *checkmark =
(UIImageView*)[tableViewCell
viewWithTag:kCheckMarkTag];
if ([number boolValue] == YES) {
checkmark.hidden = NO;
checkmark.hidden = YES;
loadPhotoForSize:GKPhotoSizeSmall
withCompletionHandler:
^(UIImage *photo,
if (!error) {
UIImageView *playerImage =
(UIImageView*)[tableView
viewWithTag:PlayerImageTag];
playerImage.image =
NSLog(@&Error loading image&);
UILabel *playerName =
(UILabel*)[tableViewCell
viewWithTag:PlayerNameTag];
playerName.text = player.displayN
UILabel *scoreLabel =
(UILabel*)[tableViewCell
viewWithTag:ScoreLabelTag];
scoreLabel.text = score.formattedV
return tableViewC
好多的代码啊。:]但是你之前使用过UITableView,这些代码对你并不陌生。tableView:cellForRowAtIndex:创建一个新的UITableViewCell。每个table view中的cell都会包含一个头像,玩家的名字和分数。
现在添加tableView:didSelectRowAtIndex:来处理用户选择table view中每一行的事件:
- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:
( *)indexPath {
BOOL isChallenged = NO;
UITableViewCell *tableViewCell =
[tableView cellForRowAtIndexPath:
indexPath];
UIImageView *checkmark =
(UIImageView*)[tableViewCell
viewWithTag:kCheckMarkTag];
if (checkmark.isHidden == NO) {
checkmark.hidden = YES;
checkmark.hidden = NO;
isChallenged = YES;
[_dataSource allValues];
array[indexPath.row];
[dict setObject:[
numberWithBool:isChallenged]
forKey:kIsChallengedKey];
[tableView deselectRowAtIndexPath:indexPath
animated:YES];
这个方法所做的是设置_dataSource的entry为YES或者NO。
编译并运行。到这里FriendsPickerViewController就可以显示出带有本地玩家的好友信息的UITableView了。每个好友的详细信息,比如名字和头像,也会被显示在每个cell中。如下图所示:
最后一件要做的事就是实际发送挑战了。把FriendsPickerViewController.m中的challengeButtonPressed:替换为以下内容:
- (void)challengeButtonPressed:
(id) sender {
if(self.challengeTextField.text.
length & 0) {
*playerIds =
*allValues =
[_dataSource allValues];
for ( *dict in allValues) {
if ([dict[kIsChallengedKey]
boolValue] == YES) {
GKPlayer *player =
dict[kPlayerKey];
[playerIds addObject:
player.playerID];
if (playerIds.count & 0) {
[[GameKitHelper sharedGameKitHelper]
sendScoreChallengeToPlayers:playerIds
withScore:_score message:
self.challengeTextField.text];
if (self.challengeButtonPressedBlock) {
self.challengeButtonPressedBlock();
self.challengeTextField.layer.
borderWidth = 2;
self.challengeTextField.layer.
borderColor =
[UIColor redColor].CGC
以下是上面方法的详细步骤分解:
此方法首先检查玩家是否输入了消息。如果没有,就把challengeTextField的边框设为红色。
如果用户输入了文本,此方法择查找所有被选中的玩家ID,并把它们保存到playerIds数组中。
如果用户选择了一个火一个以上的玩家挑战的话,则使用玩家ID作为参数调用GameKitHelper的sendScoreChallengeToPlayers:withScore:方法。此方法会发送挑战给所有已选择的玩家。
编译并运行游戏。现在当你点击FriendsPickerViewController界面的Challenge Friends按钮时,它会发送一个分数挑战。如果你有两台设备,你就可以轻易地测试它们是否工作正常了。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:69696次
积分:1050
积分:1050
排名:千里之外
转载:178篇
(1)(1)(5)(1)(1)(8)(3)(3)(16)(137)(2)(1)}

我要回帖

更多关于 game center怎么注销 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信