Menu Close

Integrating Gamecenter into libGDX | Java | Multi-OS Engine | #8

Due to the fact that the Google Play Games Services integration is not completely working on iOS (scores are not pushed to the API), I am going to write about the Multi-OS Engine Gamecenter implementation. It is not necessary to wrap the native framework to Java, because Multi-OS Engine provides bindings for GameKit under the apple.gamekit package since version 1.2.

Since iOS 10 the Gamecenter app is removed by Apple, but it is still possible to login (Settings -> Gamecenter).

Handling the Gamecenter player authentification

Player authentication with Gamecenter is very easy. You just have to register a AuthenticateHandler object once, which automatically handles the processes for you.

GKLocalPlayer localPlayer = GKLocalPlayer.localPlayer();
localPlayer.setAuthenticateHandler(new GKLocalPlayer.Block_setAuthenticateHandler() {
    @Override
    public void call_setAuthenticateHandler(UIViewController viewController, NSError nsError) {
        if (viewController != null) {
            iosApplication.getUIWindow().rootViewController().showDetailViewControllerSender(viewController, null);
        } else if (localPlayer.isAuthenticated()) {
            localPlayer.generateIdentityVerificationSignatureWithCompletionHandler(
                new GKLocalPlayer.Block_generateIdentityVerificationSignatureWithCompletionHandler() {
                @Override
                public void call_generateIdentityVerificationSignatureWithCompletionHandler(
                    NSURL publicKeyUrl, NSData signature, NSData salt, long timestamp, NSError error) {
                    //successfully logged into gamecenter
                }
            });
        } else {
            //canceled by the user or GameCenter is disabled
            //display alert view
        }
    }
});

 

Creating a leaderboard completion handler

In order to display a custom leaderboard to the player or to retrieve the best score, you have to create a leaderboard handler, where you get all leaderboards in an array. Then you may set the player and time scopes, for example to get the daily best high scores.

private boolean loading = false;
private class CompletionHandler implements GKLeaderboard.Block_loadLeaderboardsWithCompletionHandler {
    @Override
    public void call_loadLeaderboardsWithCompletionHandler(
            NSArray<? extends GKLeaderboard> leaderboards, NSError nsError) {
        //content below...
    }
}
loading = true;
if (nsError != null) {
    Log.d("Error on loading leaderboards: %s", nsError.toString());
}
if (leaderboards != null && leaderboards.size() > 0) {
    leaderboards.get(0).setPlayerScope(GKLeaderboardPlayerScope.Global);
    leaderboards.get(0).setTimeScope(GKLeaderboardTimeScope.AllTime);
    leaderboards.get(0).loadScoresWithCompletionHandler(new GKLeaderboard.Block_loadScoresWithCompletionHandler() {
        @Override
        public void call_loadScoresWithCompletionHandler(NSArray<? extends GKScore> scores, NSError nsError) {
            ...
        }
    });
}

Loading the leaderboards with your completion handler

Prevent multiple requests by simply setting a boolean variable to false, when all loading is done.

if (!loading) {
    GKLeaderboard.loadLeaderboardsWithCompletionHandler(new CompletionHandler());
}

If you get a ClassCastException when using GKScore, put the following code in your class:

static {
    try {
        Class.forName(GKScore.class.getName());
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
}

 

Submitting a score to the leaderboard

Submitting a value to the Gamecenter leaderboard is also very easy, you just have to set your leaderboard identifier, which you can find in your iTunes Connect Gamecenter page. If the nsError object is null, the score was submitted successfully, otherwise if it is not null.

GKScore gkScore = GKScore.alloc();
gkScore = gkScore.initWithLeaderboardIdentifier("my.identifier");
gkScore.setValue(42);
NSArray<GKScore> nsArray = (NSArray<GKScore>) NSArray.arrayWithObject(gkScore);
GKScore.reportScoresWithCompletionHandler(nsArray, new GKScore.Block_reportScoresWithCompletionHandler() {
    @Override
    public void call_reportScoresWithCompletionHandler(NSError nsError) {
        if (nsError != null) {
            //submitted score not successfully
        } else {
            //submitted score successfully
        }
    }
});

 

Checking if the player is logged in

Each time you want to submit a score, display a leaderboard,… you should check if the player is still authenticated with Gamecenter.

GKLocalPlayer.localPlayer().isAuthenticated();

Display an altert dialog

If the user could not be logged into Gamecenter, an altert dialog may be used to notify the user to manually login.

UIAlertView alert = UIAlertView.alloc().init();
alert.setTitle("Info");
alert.setMessage("In order to see the global High Score, please login to GameCenter (Settings -> GameCenter)");
alert.addButtonWithTitle("Ok");
alert.show();

6 thoughts on “Integrating Gamecenter into libGDX | Java | Multi-OS Engine | #8

  1. Antony Hoang

    Do you have a full code project version on github?
    I would like to check out, thanks!

  2. Antony Hoang

    but the source code in Kotlin not Java 🙁

  3. reime005

    You’re right, I haven’t published my other Java-based game yet

  4. Antony Hoang

    And one last thing, can you make a tutorial about gamecenter achievements? that would be a completion for this tutorial, thanks!

  5. reime005

    I will think about it, but I have not much free time currently

Leave a Reply

Your email address will not be published. Required fields are marked *

fourteen − eleven =

This site uses Akismet to reduce spam. Learn how your comment data is processed.