My project deals with
an app using the iPhone Game Center functionalities. As i am learning it, i have used the example from Apple documentation below:
- (void) retrieveTopTenScores
{
GKLeaderboard *leaderboardRequest = [[GKLeaderboard alloc] init];
if (leaderboardRequest != nil)
{
leaderboardRequest.playerScope = GKLeaderboardPlayerScopeGlobal;
leaderboardRequest.timeScope = GKLeaderboardTimeScopeToday;
leaderboardRequest.identifier = #"Combined.LandMaps"
leaderboardRequest.range = NSMakeRange(1,10);
[leaderboardRequest loadScoresWithCompletionHandler: ^(NSArray *scores, NSError *error) {
if (error != nil)
{
// Handle the error.
}
if (scores != nil)
{
// Process the score information.
}
}];
}
}
In principle it works fine : I do get a non-nil Score array; with one GKscore object.
However, this GKScore object is nil even though the Game Center shows that there is one score.
I have tried log-in and out of the game centre to refresh somewhat the score data from the phone GC but i can still see my score of 10.000 (as my own GC login) however every time i attempt retrieving programatically it always return null as score object...
Any tips for me or directions you could point me out?
The code works fine; it looks like there is a refresh time for the Game Center server. Yesterday, the score did appear locally on my phone, but weren't apparently not updated on the Game Center Server. Trying this morning works fine, it looks like the score data was finally updated on the server too; resulting into getting a GKScore which is no longer null.
It's interesting though to realise that when the Game Center server and the iPhone aren't in synch, it still returns non-nil Scores array only GKScore nil result... In case you have several scores in your Game Center, i guess you don't see the nil GKScore but the scores of the past days instead of the most recent.
Related
Im a beginner for developing IOS applications mainly games. I have the game completed and have submitted it to the app store. In the mere future I want to submit an update which will include game center, primarily leader boards for scores (all time, monthly, weekly, and today). I'm having trouble understanding how to integrate the completed game with game-center. Another part that is unclear to me is what do I write in the code and how does gamekit framework know which number (score) to submit to game center. If anyone could provide detailed information I'd greatly appreciate it. Thanks!
here you have a sample project
http://developer.apple.com/library/ios/#samplecode/GKTapper/Introduction/Intro.html
To send the score you have this function, score is the score, category is the name of the leaderboard you configure on itunes connect.
- (void) reportScore: (int64_t) score forCategory: (NSString*) category {
GKScore *myScoreValue = [[[GKScore alloc] initWithCategory:category] autorelease];
myScoreValue.value = score;
[myScoreValue reportScoreWithCompletionHandler:^(NSError *error){
if(error != nil){
NSLog(#"Score Submission Failed");
} else {
NSLog(#"Score Submitted");
}
}];
}
You have to use this function to send the score when your player is killed, you don't have to track if it has been the highest, but you can track if it's greater than 0;
This tutorial uses the sample project functions in his own project, take a look, it includes sending points and achivements
http://maniacdev.com/2011/05/tutorial-game-center-basics-leaderboards-and-achievements/
Game Center is available since iOS SDK 4.1
1) Open the Xcode Help.
2) On the top you should see a navigation bar, which should say "Documentation" section and move your mouse to where it says "iOS 5.1 Library"(in my case).
3) Now, move your mouse over "Networking & Internet" and click on it.
4) You now should have a list of available APIs.
After that just look around for the APIs you want, like Leaderboards, and achievements.
According to your requirements you should look for things like GKLeaderboards, and anything else you are interested in. Those documentations should link to other documentations you would need. You can find the GKLeaderboards documentation on web
Edit: The game which you developed would be showing some score to the player after each instance of the Game. Post that score to the function - (void) reportScore: (int64_t) score forCategory: (NSString*) category eg. [self.gameCenterManager reportScore:yourscore forCategory: #"yourgamecategory"];
For the GameCenterManager.h and GameCenterManager.m from this link
update score to game center use this routine.
- (void) reportScore: (int64_t) score :(NSString*) YOUR_LeaderBoard_ID
{
GKScore *scoreReporter = [[GKScore alloc] initWithCategory:YOUR_LeaderBoard_ID];
scoreReporter.value = score;
scoreReporter.context = 0;
[scoreReporter reportScoreWithCompletionHandler:^(NSError *error) {
if (error != nil)
{
IsConnectFail = true;
}else{
IsConnectFail = false;
}
}];
}
I'm trying to set up a leaderboard for my game, yet I don't know what to pass in to GKScore:initWithCategory. Looking in Itunes Connect there is "Leaderboard Reference Name" and "Leaderboard ID" both of which I have tried yet the scores still do now show up in gamecenter.
There is no mention of "category" to be found in ITC, has the terminology changed? What do I pass in to this function?
The value you need to pass is labeled as Leaderboard ID in the iTunes Connect leaderboard section.
Update:
I submit high scores to a leaderboard using the following, where category is the LeaderBoard ID as specified in iTunes Connect
GKScore *scoreReporter = [[[GKScore alloc] initWithCategory:#"yourLeaderBoardId"] autorelease];
scoreReporter.value = score;
[scoreReporter reportScoreWithCompletionHandler:^(NSError *error)
{
if (error != nil)
{
// handle the reporting error
NSLog(#"error reporting score");
}
}];
Also, it seems that in the sandbox, unless two or more distinct GameCenter accounts have submitted a score, no scores will show up.
I want a leaderboard in GameKit that shows my total accumulated score over multiple plays, not just a score from a single play. Is there any way to do this?
In other words, a single player would never have more than one entry to their name in the leaderboard. Think total experienced earned, or lifetime number of headshots. You're not going to have an entry in that leaderboard for when you had 4 headshots, and then when you had 20 headshots. You would just have the one entry for 20 lifetime headshots.
You can do this but you have to manage it yourself. GameKit is oriented around a single-game high score, not cumulative scores. Note that a player won't appear more than once on the leader board because GKLeaderboard will only report back the highest score in the time range you specified.
Tracking a cumulative score isn't that hard. Here's some code I'm using to do this. Get the GKLeaderboard with the ID that is tracking the score, and then fetch the high score for the local user. Then, add the new total to the current high score and then report the new total.
- (void)updateLeaderboardWithID:(NSString *)identifier score:(int64_t)score {
GKLeaderboard* leaderBoard= [[GKLeaderboard alloc] init];
leaderBoard.category = identifier;
leaderBoard.timeScope = GKLeaderboardTimeScopeAllTime;
leaderBoard.range = NSMakeRange(1, 1);
[leaderBoard loadScoresWithCompletionHandler: ^(NSArray *scores, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^(void) {
GKScore *localScore = leaderBoard.localPlayerScore;
int64_t newValue = localScore.value + score;
localScore = [[GKScore alloc] initWithCategory:identifier];
localScore.value = newValue;
[localScore reportScoreWithCompletionHandler:^(NSError *error){
// error handling goes here
}];
);
}];
}
Yes,It may be possible. But you have to read apple documentary.This is all about GKLeaderBoardViewController class.
You can use GKLeaderBoardViewController class for counting Highest Score.
http://developer.apple.com/library/ios/#documentation/GameKit/Reference/GKLeaderboardViewController_Ref/Reference/Reference.html
Im a noob in game center # games generally. Im making my second game now and implemented the game center.
If the internet is available, there is no problem, everything works well.
But just now I purposely make the internet unreachable, and when I get an achievement, obviously it does not register to the Game Center's Achievement.
How and what's the best way to handle this issue?
Thank you....
You could add the GKAchievement objects that fail to register to an array and then resend them when you get back connectivity. You should also consider committing that array to persistent storage, in case your app terminates before it has a chance to send those achievements. Try this in your completion handler:
// Load or create array of leftover achievements
if (achievementsToReport == nil) {
achievementsToReport = [[NSKeyedUnarchiver unarchiveObjectWithFile:pathForFile(kAchievementsToReportFilename)] retain];
if (achievementsToReport == nil) {
achievementsToReport = [[NSMutableArray array] retain];
}
}
#synchronized(achievementsToReport) {
if(error == nil)
{
// Achievement reporting succeded
// Resend any leftover achievements
BOOL leftoverAchievementReported = NO;
while ([achievementsToReport count] != 0) {
[self resendAchievement:[achievementsToReport lastObject]];
[achievementsToReport removeLastObject];
leftoverAchievementReported = YES;
}
// Commit leftover achievements to persistent storage
if (leftoverAchievementReported == YES) {
[NSKeyedArchiver archiveRootObject:achievementsToReport toFile:pathForFile(kAchievementsToReportFilename)];
}
}
else
{
// Achievement reporting failed
[achievementsToReport addObject:theAchievement];
[NSKeyedArchiver archiveRootObject:achievementsToReport toFile:pathForFile(kAchievementsToReportFilename)];
}
}
Hope this helps.
I see that the two answers here focus on the specific mechanisms for archiving the undelivered achievement messages. For a higher-level description of the overall approach, you can see my answer to this related question: Robust Game Center Achievement code
Achievements (and all of the gamecenter stuff like leaderboard updates) conform to NSCoding. You can store them if you get an error submitting them and submit them later. This is what apple recommends in their docs.
Your application must handle errors when it fails to report progress to Game Center. For example, the device may not have had a network when you attempted to report the progress. The proper way for your application to handle network errors is to retain the achievement object (possibly adding it to an array). Then, your application needs to periodically attempt to report the progress until it is successfully reported. The GKAchievement class supports the NSCoding protocol to allow your application to archive an achievement object when it moves into the background.
from: http://developer.apple.com/library/ios/#documentation/NetworkingInternet/Conceptual/GameKit_Guide/Achievements/Achievements.html#//apple_ref/doc/uid/TP40008304-CH7-SW13
// Submit an achievement to the server and store if submission fails
- (void)submitAchievement:(GKAchievement *)achievement
{
if (achievement)
{
// Submit the achievement.
[achievement reportAchievementWithCompletionHandler: ^(NSError *error)
{
if (error)
{
// Store achievement to be submitted at a later time.
[self storeAchievement:achievement];
}
else
{
NSLog(#"Achievement %# Submitted..",achievement);
if ([storedAchievements objectForKey:achievement.identifier]) {
// Achievement is reported, remove from store.
[storedAchievements removeObjectForKey:achievement.identifier];
}
[self resubmitStoredAchievements];
}
}];
}
}
In case anyone stumbles upon this question in the future, Apple now has sample code for submitting achievements that includes a way to archive achievements that failed to submit (due to no network connection, etc). You'll find it in the Game Center programming guide.
I have my app give a notification when a Game Center achievement is achieved/reaches 100%, however it shows the notification every times the user completes it, but I only want it to notify the first time in actually completed.
I found this in the Apple docs:
http://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/GameKit_Guide/Achievements/Achievements.html#//apple_ref/doc/uid/TP40008304-CH7-SW11
However didn't quite understand how it help fix my issue.
I only want to call this notification once, when the achievement is first achieved. So only show it if its not already achieved.
Edit
I have this to unlock the achievement:
- (void) reportAchievementIdentifier: (NSString*) identifier percentComplete: (float) percent
{
GKAchievement *achievement = [[[GKAchievement alloc] initWithIdentifier: identifier] autorelease];
if (achievement)
{
achievement.percentComplete = percent;
[achievement reportAchievementWithCompletionHandler:^(NSError *error)
{
if (error != nil)
{
// Retain the achievement object and try again later (not shown).
}
}];
}
}
And unlock with this:
[self reportAchievementIdentifier:identifier percentComplete:percent];
Then show the notification with this line:
[[GKAchievementHandler defaultHandler] notifyAchievementTitle:#"Title" andMessage:#"Message"];
So do I simply need something like this in that code chunk?
if (achievement.completed != TRUE) {
[[GKAchievementHandler defaultHandler] notifyAchievementTitle:#"Title" andMessage:#"Message"];
}
There's a "completed"-property in GKAchievement... Try to make a new GKAchievement and check if it's not completed, then unlock it.