I would like to download score from GameCenter, but I don't know how to wait, when score is downloaded. When I run this code, it returns null. I think, that method have to wait when [leaderboardRequest loadScoresWithCompletionHandler: ... will have score downloaded.
- (NSString*) getScore: (NSString*) leaderboardID
{
__block NSString *score = nil;
GKLeaderboard *leaderboardRequest = [[GKLeaderboard alloc] init];
if (leaderboardRequest != nil)
{
leaderboardRequest.identifier = leaderboardID;
[leaderboardRequest loadScoresWithCompletionHandler: ^(NSArray *scores, NSError *error) {
if (error != nil)
{
NSLog(#"%#", [error localizedDescription]);
}
if (scores != nil)
{
int64_t scoreInt = leaderboardRequest.localPlayerScore.value;
score = [NSString stringWithFormat:#"%lld", scoreInt];
}
}];
}
return score;
}
The code from the completion handler will be called when the operation is complete (on another thread).
You have several options there, you can store the score somewhere and post a notification to notify the main thread that the operation is completed.
Related
I'm trying to implement a real-time multiplayer game with a custom UI (no GKMatchMakerViewController). I'm using startBrowsingForNearbyPlayersWithReachableHandler:
^(NSString *playerID, BOOL reachable) to find a local player, and then initiating a match request with the GKMatchmaker singleton (which I have already initiated).
Here's where I'm having trouble. When I send a request, the completion handler fires almost immediately, without an error, and the match it returns has an expected player count of zero. Meanwhile, the other player definitely has not responded to the request.
Relevant code:
- (void) findMatch
{
GKMatchRequest *request = [[GKMatchRequest alloc] init];
request.minPlayers = NUM_PLAYERS_PER_MATCH; //2
request.maxPlayers = NUM_PLAYERS_PER_MATCH; //2
if (nil != self.playersToInvite)
{
// we always successfully get in this if-statement
request.playersToInvite = self.playersToInvite;
request.inviteeResponseHandler = ^(NSString *playerID, GKInviteeResponse
response)
{
[self.delegate updateUIForPlayer: playerID accepted: (response ==
GKInviteeResponseAccepted)];
};
}
request.inviteMessage = #"Let's Play!";
[self.matchmaker findMatchForRequest:request
withCompletionHandler:^(GKMatch *match, NSError *error) {
if (error) {
// Print the error
NSLog(#"%#", error.localizedDescription);
}
else if (match != nil)
{
self.currentMatch = match;
self.currentMatch.delegate = self;
// All players are connected
if (match.expectedPlayerCount == 0)
{
// start match
[self startMatch];
}
[self stopLookingForPlayers];
}
}];
}
Figured it out! I needed to call - (void)matchForInvite:(GKInvite *)invite completionHandler:(void (^)(GKMatch *match, NSError *error))completionHandler in my invitation handler so that both players have the same match data.
I am not knowing anything about gamecentre.I am working on the COCO application
I had gone through gamecenter guide and get able to integrate the game center in my application.
1)
Now the i am able enter the score in the gamecentre through my application.
By doing this:-
- (void) reportScore: (int64_t) score forCategory: (NSString*) category
{
GKScore *scoreReporter = [[[GKScore alloc] initWithCategory:category] autorelease];
scoreReporter.value = score;
[scoreReporter reportScoreWithCompletionHandler: ^(NSError *error)
{
[self callDelegateOnMainThread: #selector(scoreReported:) withArg: NULL error: error];
}];
}
I is working properly uptil yesterday.But now if i tried to update the score it is not updating.Please any one know the reason y the score is not updating in the game center
I had tried to search out but not get anything.
2)I want to send the current latitude & longitude of one player to another.
I came to know that it is possible by GKMATCH
GKMatchRequest *request = [[[GKMatchRequest alloc] init] autorelease];
request.minPlayers = 1;
request.maxPlayers = 1;
[[GKMatchmaker sharedMatchmaker] findMatchForRequest:request
withCompletionHandler:^(GKMatch *match, NSError *error) {
if (error || !match) {
// handle the error
}
else if (match != nil){
// match found
}}];
/*GKMatchRequest *request = [[[GKMatchRequest alloc] init] autorelease];
request.minPlayers = 1;
request.maxPlayers = 1;
GKMatchmakerViewController *mmvc = [[GKMatchmakerViewController alloc] initWithMatchRequest:request];
mmvc.matchmakerDelegate = self;
currentMatch.delegate=self;
[self presentModalViewController:mmvc animated:YES];*/
//[mmvc release];
}
- (void)match:(GKMatch *)match player:(NSString *)playerID didChangeState:(GKPlayerConnectionState)state {
switch (state){
case GKPlayerStateConnected:
if (match.expectedPlayerCount == 0) {
// start the match
}
break;
case GKPlayerStateDisconnected:
// remove the player from the match, notify other players, etc
break;
}
}
- (void)matchmakerViewControllerWasCancelled:(GKMatchmakerViewController *)viewController{}
// Matchmaking has failed with an error
- (void)matchmakerViewController:(GKMatchmakerViewController *)viewController didFailWithError:(NSError *)error{
}
// A peer-to-peer match has been found, the game should start
- (void)matchmakerViewController:(GKMatchmakerViewController *)viewController didFindMatch:(GKMatch *)match{
}
// Players have been found for a server-hosted game, the game should start
- (void)matchmakerViewController:(GKMatchmakerViewController *)viewController didFindPlayers:(NSArray *)playerIDs{
}
// An invited player has accepted a hosted invite. Apps should connect through the hosting server and then update the player's connected state (using setConnected:forHostedPlayer:)
- (void)matchmakerViewController:(GKMatchmakerViewController *)viewController didReceiveAcceptFromHostedPlayer:(NSString *)playerID {
}
- (void) sendPosition
{
NSError *error;
NSString* str = #"teststring";
NSData* data = [str dataUsingEncoding:NSUTF8StringEncoding];
// NSData *packet = [NSData dataWithBytes:&msg length:sizeof(PositionPacket)];
[currentMatch sendDataToAllPlayers: data withDataMode: GKMatchSendDataUnreliable error:&error];
if (error != nil)
{
// Handle the erro.r
}
}
But i dont know why but delegate method of GKMatchmakerViewController is not called i had set the delegate but still and even i ama not able to get GKMATCH (here currentMatch).
So due to this
[currentMatch sendDataToAllPlayers: data withDataMode: GKMatchSendDataUnreliable error:&error];
this method is not working.
as CurrentMatch refrence is 0X0.
Please help me out.How do i send and recive data.
M i doing anything wrong?OR is there any thing else to be done.
Please help me.
Thanks
I'm trying to make a leaderboard in my game with Game Center. I post the high score like so:
GKScore *myScoreValue = [[[GKScore alloc] initWithCategory:#"grp.high_scores"] autorelease];
myScoreValue.value = self.game.scoreMeter.score;
NSLog(#"Attemping to submit score: %#", myScoreValue);
[myScoreValue reportScoreWithCompletionHandler:^(NSError *error){
if(error != nil){
NSLog(#"Score Submission Failed");
} else {
NSLog(#"Score Submitted");
id appDelegate = [[UIApplication sharedApplication] delegate];
[appDelegate displayLeaderBoard:nil];
}
}];
I see "Score Submitted" as expecting, and it brings up the Game Center leaderboard view, but it just reads "No Scores"
I know other people have said you need at least two accounts, but I've tried with three already.
For each account, the game shows up for them in the Game Center App, and when I query for the top ten scores:
- (void) retrieveTopTenScores
{
GKLeaderboard *leaderboardRequest = [[GKLeaderboard alloc] init];
if (leaderboardRequest != nil)
{
leaderboardRequest.playerScope = GKLeaderboardPlayerScopeGlobal;
leaderboardRequest.timeScope = GKLeaderboardTimeScopeAllTime;
leaderboardRequest.range = NSMakeRange(1,10);
[leaderboardRequest loadScoresWithCompletionHandler: ^(NSArray *scores, NSError *error) {
if (error != nil)
{
NSLog(#"Error grabbing top ten: %#", error);
}
if (scores != nil)
{
NSLog(#"Top ten scores: %#", scores);
}
}];
}
}
each user only sees their own score.
So why is the leaderboard empty, and why is each user only seeing their own score?
Sandbox can be messy sometimes, but let me ask you this. Is your self.game.scoreMeter.score an int?
If so, try doing this:
myScoreValue.value = [[NSNumber numberWithInt:self.game.scoreMeter.score] longLongValue];
for setting the value of the GKScore object. Let me know if it changes anything.
Well, it turns out you need to be signed in to game center with a developer sandbox account for it to work correctly
I have built objectives for my game and everything works just fine accept the part of making the objectives not be called any more after any of them is completed.
I know there is a Property of the GKAchievement Class "completed" which is a boolean that returns yes when the Achievement is 100 percent done.
here is the method that called when a Achievement is 100 percent done it passes id which is the Achievement identifier and report the acheeee :
- (void)AchivmentDidAchive:(id)Achivment{
NSString *identifier = Achivment;
NSLog(#"%#",identifier);
self.achivment = [[GKAchievement alloc]initWithIdentifier:identifier];
self.achivment.showsCompletionBanner = YES;
if (!self.achivment.completed) {
self.achivment.percentComplete = 100;
NSLog(#"Reproting!");
[self.achivment reportAchievementWithCompletionHandler: ^(NSError *error)
{
}];
}
else {
NSLog(#"Achivment Completed!");
} }
what I am trying to do here is to set the percent completed to 100 and report it so in the next time ie want get called again.
but it always works... any better idea for how to handle this?
in interface add variable & property:
NSMutableDictionary *earnedAchievementCache;
#property (nonatomic, retain)NSMutableDictionary *earnedAchievementCache;
in .m:
#synthesize earnedAchievementCache;
- (void) submitAchievement: (NSString*) identifier percentComplete: (double) percentComplete
{
if(self.earnedAchievementCache == NULL)
{
[GKAchievement loadAchievementsWithCompletionHandler: ^(NSArray *scores, NSError *error)
{
if(error == NULL)
{
NSMutableDictionary* tempCache= [NSMutableDictionary dictionaryWithCapacity: [scores count]];
for (GKAchievement* score in scores)
{
[tempCache setObject: score forKey: score.identifier];
}
self.earnedAchievementCache= tempCache;
[self submitAchievement: identifier percentComplete: percentComplete];
}
}];
}
else
{
GKAchievement* achievement= [self.earnedAchievementCache objectForKey: identifier];
if(achievement != NULL)
{
if((achievement.percentComplete >= 100.0) || (achievement.percentComplete >= percentComplete))
{
achievement= NULL;
}
achievement.percentComplete= percentComplete;
}
else
{
achievement= [[[GKAchievement alloc] initWithIdentifier: identifier] autorelease];
achievement.percentComplete= percentComplete;
[self.earnedAchievementCache setObject: achievement forKey: achievement.identifier];
}
if(achievement!= NULL)
{
//Submit the Achievement...
if (achievement.percentComplete>=100) {
//show banner
achievement.showsCompletionBanner = YES; //only in IOS 5+
}
[achievement reportAchievementWithCompletionHandler: ^(NSError *error)
{
if (error!=NULL){
NSLog(#"Error!!");
} else NSLog(#"all is well");
}];
}
}
}
in dealloc :
[self.earnedAchievementCache release];
i'm using the cache to not submit scores already submitted / completed
PS: the code is perfect just copy and paste it into your class and it will work
this is what I use in my helper Game Center class:
-(void) reportAchievementWithID:(NSString*) AchievementID {
[GKAchievement loadAchievementsWithCompletionHandler:^(NSArray *achievements, NSError *error) {
if(error) NSLog(#"error");
for (GKAchievement *ach in achievements) {
if([ach.identifier isEqualToString:AchievementID]) { //already submitted
NSLog(#"Already submitted");
return ;
}
}
GKAchievement *achievementToSend = [[GKAchievement alloc] initWithIdentifier:AchievementID];
achievementToSend.percentComplete = 100;
achievementToSend.showsCompletionBanner = YES;
[achievementToSend reportAchievementWithCompletionHandler:NULL];
}];
}
note: I don't use percentages in my achievements, so you'd need to modify things a little bit if you do.
I'm doing an ios app based on maths..
I've done the code for uploading the high score to the Game Center..
but this doesn't work..
it's always showing 0 as the high score..
This is my code...
[[GKLocalPlayer localPlayer]authenticateWithCompletionHandler:^(NSError *error)
{
if (error ==nil)
{
CCLOG(#"Success");
} else
{
CCLOG(#"Fail");
}
}];
.
.
.
.
.
-(void)showLeaderboard
{
if( ! gameCenterViewController_ )
gameCenterViewController_ = [[GameCenterViewController alloc] init];
[gameCenterViewController_ showLeaderboard];
}
-(void)submitMyScore1:(int)score1
{
CCLOG(#"submitMyScore1--%d",score1);
//This is the same category id you set in your itunes connect GameCenter LeaderBoard
GKScore *myScoreValue = [[[GKScore alloc] initWithCategory:#"bigwizlist"] autorelease];
myScoreValue.value = score1;
[myScoreValue reportScoreWithCompletionHandler:^(NSError *error){
if(error != nil)
{
CCLOG(#"Score Submission Failed");
} else
{
CCLOG(#"Score Submitted");
}
}];
}
I think you need to use an int64_t for your method! I use this method and it works perfectly fine :-)
-(void)submitScore:(int64_t)score category:(NSString*)category{
GKScore *gkScore = [[[GKScore alloc]initWithCategory:category]autorelease];
gkScore.value = score;
[gkScore reportScoreWithCompletionHandler:^(NSError* error)
{
[self setLastError:error];
bool sucess = (error == nil);
[delegate onScoresSubmitted:sucess];
}];
}
Greetings
Anselm