This is the best way to integrate the GameCenter LeaderBoard to your AppGameKit game.
It will be really easy and fast, in only some lines, directly in your UntitledViewController without subclassing and without external classes.
1. Link Library
Go to the project build window and link libraries.
Press add libraries and chose GameKit.framework.
If when you add the library goes out of your Framework group (folder) drag it into the one you want and after drag again it from the folder to the link libraries window (this is a trick to do faster).
2. Importing library
We have to import it to our
UntitledViewController.h adding this line to the header.
#import <GameKit/GameKit.h>
3. Adding the delegates
Usually when you open the UntitledViewController.h file you see this:
@interface UntitledViewController : UIViewController
{
EAGLContext *context;
GLuint program;
BOOL active;
BOOL displayLinkSupported;
NSInteger frameInterval;
id displayLink;
NSTimer *syncTimer;
}
Now you have to add the delegate to the interface, to let the GameCenter know who control the window for the Leaderboards. So it will be in this way:
@interface UntitledViewController : UIViewController <GKLeaderboardViewControllerDelegate>
{
EAGLContext *context;
GLuint program;
BOOL active;
BOOL displayLinkSupported;
NSInteger frameInterval;
id displayLink;
NSTimer *syncTimer;
}
4. Adding the functions
Now as we declared the delegate, we can start to add the main functions to use in the files...
- (void) AuthLocalPlayer;
- (void) TopScore;
- (BOOL) isGameCenterAvailable;
- (void) submitScore: (int64_t) _score;
- (void) showLeaderboard;
Now is the time to open the
UntitledViewController.m and add the code for the functions.
//****************************************************
// GAME CENTER
//****************************************************
- (void) AuthLocalPlayer
{
if([self isGameCenterAvailable]){
[[GKLocalPlayer localPlayer] authenticateWithCompletionHandler:^(NSError *error) {
if([GKLocalPlayer localPlayer].isAuthenticated){
//[self TopScore];
}
}];
} else {
[self showAlertWithTitle: @"Game Center Support Required!" :@"The current device does not support Game Center."];
}
}
- (BOOL) isGameCenterAvailable
{
// Check for presence of GKLocalPlayer class.
BOOL localPlayerClassAvailable = (NSClassFromString(@"GKLocalPlayer")) != nil;
//Note this is old way to use it, now you can check only the class (*GEKKO)
// The device must be running iOS 4.1 or later.
NSString *reqSysVer = @"4.1";
NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
BOOL osVersionSupported = ([currSysVer compare:reqSysVer options:NSNumericSearch] != NSOrderedAscending);
return (localPlayerClassAvailable && osVersionSupported);
}
- (void) submitScore: (int64_t) _score
{
GKScore *myScoreValue = [[[GKScore alloc] initWithCategory:@"MY_Game"] autorelease];
myScoreValue.value = _score;
[myScoreValue reportScoreWithCompletionHandler:^(NSError *error){
if(error != nil){
//Failed..add your code
} else {
//OK...add your code
}
}];
}
- (void)showLeaderboard
{
//[[UIApplication sharedApplication] setStatusBarOrientation: UIInterfaceOrientationLandscapeLeft];
GKLeaderboardViewController *leaderboardController = [[[GKLeaderboardViewController alloc] init] autorelease];
if (leaderboardController != NULL){
leaderboardController.category = @"MY_Game";
leaderboardController.timeScope = GKLeaderboardTimeScopeAllTime;
leaderboardController.leaderboardDelegate = appDelegate.viewController;
[appDelegate.viewController presentModalViewController:leaderboardController animated:YES];
}
}
- (void) TopScore
{
GKLeaderboard *leaderboardRequest = [[GKLeaderboard alloc] init];
if (leaderboardRequest != nil){
leaderboardRequest.category = @"My_Game";
leaderboardRequest.playerScope = GKLeaderboardPlayerScopeGlobal;
leaderboardRequest.timeScope = GKLeaderboardTimeScopeAllTime;
leaderboardRequest.range = NSMakeRange(1, 1);
[leaderboardRequest loadScoresWithCompletionHandler: ^(NSArray *scores, NSError *error) {
if (error != nil){
Opzioni[0].best_score = "None";
} else {
GKScore *pun = [scores objectAtIndex:0];
int64_t value = pun.value;
Opzioni[0.].best_score = [[NSString stringWithFormat:@"%i", value] UTF8String];
}
}];
}
}
- (void)leaderboardViewControllerDidFinish:(GKLeaderboardViewController *)viewController
{
[appDelegate.viewController dismissModalViewControllerAnimated:YES];
}
When you see "My_Game" you need to change it with the Category Name you chose in the ITUNES CONNECT when you allow your app for the GameCenter.
In this code, i use this declaration to get a global application delegate variable, don't use SELF, it will not work as you expect;
appDelegate = (iphone_appAppDelegate *) [[UIApplication sharedApplication] delegate];
I also included the TopScore function to give you the possibility to understand how to retrieve the top 10 or the RANGE you want.
Now all you have to do is to call the [self AuthLocalPlayer] function to start it.
Trick to have the UntitledViewController in the C++ AGK
Add this line to your declaration in the AppGameKit template.c;
UntitledViewController *VC = [UntitledViewController alloc];
As you see you need only to alloc, as the init will be done from the UntitledViewController.m
From this moment you can use the Obj C functions also in the C++, like this:
[VC ShowLeaderboard];
or if you want to start the Game Center from C++ line in your agk::begin or your preferred function:
[VC AuthLocalPlayer];
How to submit a score
int64_t myscore;
myscore = 500;
[VC submitScore :myscore];
Example code to add Player struct in AppGameKit shared with Obj C
Open your template.h
struct _Player { string nick; int64_t score; };
extern vector <_Player> Player;
// Now you can use Player struct also in UntitledViewController.h and .m
// Remember to check the #import files sequence to be sure of that :D
Open your template.c
vector <_Player> Player(1); //If you have more add it to the array
Retrieve the GameCenter Nick (add this in your AuthLocalPlayer after all is ok)
Player[0].nick = [GKLocalPlayer localPlayer].alias.UTF8String;
Anywhere in your code:
//You done some score and now we wanna store
Player[0].score = 723654;
[VC submitScore :Player[0].score;
Remember:
1. You need agk::Sync() some times to change effects on the main view.
No problem if you use the loop control it for you.
2.You need to study a good #import or #include (if you prefer, i prefer import) timeline, probably if you have some errors is cause you mixed too times the same includes and import.
Give a look and try to do less files and avoid to write the same import too times.
If you wanna know more don't hesitate to ask!
Enjoy.
(Moderator can you delete the next post, i done a mistake sorry and thx)
Long life to Steve!