IOS-integrated game center (leader board)
The leader board in the game center has been used again recently. In fact, this is very simple, but it is easy to forget. So I plan to write it down.
Create an app on iTunes Connect and enable game center
The creation of the app is omitted. After the creation is successful, you do not need to submit the application. We can set the game center.
First, click the newly created app and find the Game Center,
Click to go to the specific game center settings to add some projects. It is very simple, basically there are prompts, you need to pay attention to the ranking id, you have to make an independent, do not repeat. This id is required in the code.
In this simple way, game center is enabled.
Introduce game center in code
Open game center in the xcode project,
<喎?http: www.bkjia.com kf ware vc " target="_blank" class="keylink"> VcD4KPHA + 1rG907Tyv6q + examples/CwLS + zcrHvt/examples + cve-vcd4kpha + PHN0cm9uZz60 + examples + ytfPyNTaus/examples/watermarks = "brush: java; "> double ver = [[UIDevice currentDevice]. systemVersion doubleValue]; if (ver <6.0) {[[GKLocalPlayer localPlayer] authenticateWithCompletionHandler: ^ (NSError * error) {}];} else {[[GKLocalPlayer localPlayer] setAuthenticateHandler :( ^ (UIViewController * viewcontroller, NSError * error) {})];} nsicationicationcenter * ns = [nsicationicationcenter defacenter]; [ns addObserver: self selector: @ selector (authenticationChanged) name: GKPlayerAuthenticationDidChangeNotificationName object: nil];We have added an observer to the game center, so we need to provide a function in self. This is a callback function. If the user does not log on to the game center, the user will log on to the following page. If the user logs on to the game center, the user will log on to the game center.
- (void) authenticationChanged{ if ([GKLocalPlayer localPlayer].isAuthenticated) { NSLog(@"authenticationChanged, authenticated"); } else { NSLog(@"authenticationChanged, Not authenticated"); }}
Next, submit and display the leader board. The specific description on Apple's official website is clear. I found an encapsulated source code on the Internet and modified it slightly. The specific code is shown at the end (attached ). This section describes the procedure. Add an attribute first.
@property (readwrite, retain) PlayerModel * player;
Add another function, such:
- (void) updatePlayer{ if (!self.player || ![self.player.currentPlayerID isEqualToString:[GKLocalPlayer localPlayer].playerID]) { [self.player release]; self.player = [[PlayerModel alloc] init]; } [[self player] loadStoredScores];}This function will be tuned to in authenticationChanged.
- (void) authenticationChanged{ if ([GKLocalPlayer localPlayer].isAuthenticated) { NSLog(@"authenticationChanged, authenticated"); [self updatePlayer]; } else { NSLog(@"authenticationChanged, Not authenticated"); }}UpdatePlayer is a key function.
It supports multiple users. If this is the first time you log on to the game center, you can create an object. If you log on with another user, you can release the previous one and create a new object. Call loadStoredScore.
LoadStoredScore reads the score to be transferred from the local file and transmits it to the game center server.
The above Code indicates that after the app is started, authenticationChanged is called. If it is in the logon status, a PlayerModel object will be created. If there is data to be uploaded, read and try to upload.
In fact, this is a protection measure, and we will discuss why we need to do so later.
Next let's take a look at how to upload data instantly in the game.
First, add a function that sends data to the server. Self. player submitScore, which will be viewed later. With this function, we can call somewhere in the game or application to send data to the server. The LEADERBOARD_DISTANCE value is the ranking id created in connect.
- (void) storeScore:(NSNumber *)distance{ if (!self.player) return; int64_t score64 = [distance longLongValue]; GKScore * submitScore = [[GKScore alloc] initWithCategory:LEADERBOARD_DISTANCE]; [submitScore setValue:score64]; [self.player submitScore:submitScore]; [submitScore release];}
OK, that's simple. Now let's talk about the principles of PlayerModel. Because we often fail due to network reasons when submitting, especially in China. Therefore, a mechanism is submitted in PlayerModel. If the submission fails, the data to be submitted will be saved to the local file and submitted again when appropriate.
- (void)submitScore:(GKScore *)score { if ([GKLocalPlayer localPlayer].authenticated) { if (!score.value) { // Unable to validate data. return; } // Store the scores if there is an error. [score reportScoreWithCompletionHandler:^(NSError *error){ if (!error || (![error code] && ![error domain])) { // Score submitted correctly. Resubmit others [self resubmitStoredScores]; } else { // Store score for next authentication. [self storeScore:score]; } }]; } }The main meaning of this function is to try to submit the data first. If the data is successfully submitted, submit other data (the data may have failed to be submitted before ). If it fails, save the data [self storeScore: score], save it to an array, and write it to a local file. In this way, you will have the opportunity to submit it again elsewhere. The complete code is later.
Now let's see if the leader board is displayed in the app. The following code gameCenterAuthenticationComplete is a bool used internally to mark whether the user has logged on to the game center. Call this code to display the game center of iOS.
- (void) showGameCenter{ if (gameCenterAuthenticationComplete) { GKLeaderboardViewController * leaderboardViewController = [[GKLeaderboardViewController alloc] init]; [leaderboardViewController setCategory:LEADERBOARD_DISTANCE]; [leaderboardViewController setLeaderboardDelegate:_viewController]; [self.viewController presentModalViewController:leaderboardViewController animated:YES]; [leaderboardViewController release]; }}
Appendix, complete PlayerModle code:
Header file:
#import
#import
@interface PlayerModel : NSObject {NSLock *writeLock;}@property (readonly, nonatomic) NSString* currentPlayerID;@property (readonly, nonatomic) NSString *storedScoresFilename;@property (readonly, nonatomic) NSMutableArray * storedScores;// Store score for submission at a later time.- (void)storeScore:(GKScore *)score ;// Submit stored scores and remove from stored scores array.- (void)resubmitStoredScores;// Save store on disk. - (void)writeStoredScore;// Load stored scores from disk.- (void)loadStoredScores;// Try to submit score, store on failure.- (void)submitScore:(GKScore *)score ;@end
M file:
#import "PlayerModel.h"@implementation PlayerModel@synthesize storedScores, currentPlayerID, storedScoresFilename;- (id)init{ self = [super init]; if (self) { currentPlayerID = [[NSString stringWithFormat:@"%@", [GKLocalPlayer localPlayer].playerID] retain]; NSString* path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; storedScoresFilename = [[NSString alloc] initWithFormat:@"%@/%@.storedScores.plist",path, currentPlayerID]; writeLock = [[NSLock alloc] init]; } return self;}- (void)dealloc{ [storedScores release]; [writeLock release]; [storedScoresFilename release]; [currentPlayerID release]; [super dealloc];}// Attempt to resubmit the scores.- (void)resubmitStoredScores{ if (storedScores) { // Keeping an index prevents new entries to be added when the network is down int index = (int)[storedScores count] - 1; while( index >= 0 ) { GKScore * score = [storedScores objectAtIndex:index]; [self submitScore:score]; [storedScores removeObjectAtIndex:index]; index--; } [self writeStoredScore]; }}// Load stored scores from disk.- (void)loadStoredScores{ NSArray * unarchivedObj = [NSKeyedUnarchiver unarchiveObjectWithFile:storedScoresFilename]; if (unarchivedObj) { storedScores = [[NSMutableArray alloc] initWithArray:unarchivedObj]; [self resubmitStoredScores]; } else { storedScores = [[NSMutableArray alloc] init]; }}// Save stored scores to file. - (void)writeStoredScore{ [writeLock lock]; NSData * archivedScore = [NSKeyedArchiver archivedDataWithRootObject:storedScores]; NSError * error; [archivedScore writeToFile:storedScoresFilename options:NSDataWritingFileProtectionNone error:&error]; if (error) { // Error saving file, handle accordingly } [writeLock unlock];}// Store score for submission at a later time.- (void)storeScore:(GKScore *)score { [storedScores addObject:score]; [self writeStoredScore];}// Attempt to submit a score. On an error store it for a later time.- (void)submitScore:(GKScore *)score { if ([GKLocalPlayer localPlayer].authenticated) { if (!score.value) { // Unable to validate data. return; } // Store the scores if there is an error. [score reportScoreWithCompletionHandler:^(NSError *error){ if (!error || (![error code] && ![error domain])) { // Score submitted correctly. Resubmit others [self resubmitStoredScores]; } else { // Store score for next authentication. [self storeScore:score]; } }]; } }@end