Navigation

Part 6 - Loading and Saving Stats

The Facebook API allows you to save statistics about your game to the cloud storage associated with the current player. These are not to be confused with analytics, rather they let you save in-game values which you wish to persist across play sessions. For example, you could save the level they reached, the amount of gold won so far, the amount of baddies slain, etc.

Once important thing to note is that stats must be integers. You cannot save floats or textual data using these functions. With that limitation aside, let's write some code to save, retrieve and modify them.

Saving Stats

For the sake of this example we're going to save some stats for an RPG type game.

There are three plugin functions you can use, the first of which is saveStats. Take a look at the following code:

this.facebook.on('savestats', function (data) {

    //  Handle what the game should do after the stats have saved

});

this.facebook.on('savestatsfail', function (error) {

    //  Handle what the game should do if the stats fail to save

});

var defaultHuman = {
    level: 1,
    race: 0,
    gold: 500,
    strength: 32,
    hitpoints: 40,
    wisdom: 9,
    dexterity: 4
};

this.facebook.saveStats(defaultHuman);

This code will send the properties and values set in the defaultHuman object to Facebooks cloud storage. This is a per-player storage system, so anything you record in here will only be available to the current player.

When the stats have saved it will emit the savestats event. If, for whatever reason, they fail to save, it will emit the savestatsfail event instead, containing the error response. This is a pattern it's worth getting familiar with as the Phaser Instant Games plugin uses it extensively. This is because all calls to the platform are asynchronous, which means they don't happen immediately, and instead the plugin waits for the response back before notifying you of the success, or failure, via the internal events system.

Once you receive the savestats event, you know your stats are saved in cloud storage for that player.

Updating Stats

There are two ways to update the stats stored for the player. The first is to simply call saveStats again and provide some new values. Based on our previous example, if you were to now call the following code:

var changedStats = {
    level: 2,
    hitpoints: 11,
    poison: 9
};

this.facebook.saveStats(changedStats);

What would happen is the following:

  1. The level stat, which was saved in our first call as 1, would be updated to the new value of 2.
  2. The hitpoints stat, which was previously 40, would be updated to the new value of 11.
  3. The new stat poison, which didn't exist before, would be created and given a value of 9.

As you can see, clearly something quite dramatic befell our hero as they're now poisoned and running low on hp. What's important to understand is that when you re-save a statistic with a new value, the old value is replaced.

If you add in a new statistic, with a previously un-saved name (like poison in our example above), then it will be added to the rest of the stats that are already present.

At the time of writing, in version 6.2 of the Facebook SDK, there's no way to remove a statistic once saved.

Incrementing Stats

The other way to modify a stat is to increment it, rather than save over it.

Because stats are purely numeric you're able to modify them, rather than replace their values directly. You do this via the incStats method. Let's say our damaged hero stumbles across a minor health potion. We can issue the following command to reflect this:

this.facebook.on('incstats', function (data) {

    //  Handle what the game should do after the stats have incremented

});

this.facebook.on('incstatsfail', function (error) {

    //  Handle what the game should do if the stats fail to increment

});

this.facebook.incStats({ hitpoints: 20, poison: -7 });

Here, the values we pass are modifiers for those already stored. In this case we're adding 20 to the hitpoints stat. It was previously 11, so after this call it will now be 31. We're also reducing the poison value by 7, because of the minus-sign infront of the value, which makes our hero's poison level now just 2.

Depending on the stats you're tracking it's up to you to decide if it's easier to issue an increment update, or just save over the original values. If you get to the point where you're storing large numbers then it would save in network traffic to send small increment modifiers instead of re-sending the large values again.

Getting Stats

To get the game stats from cloud storage you need to use the getStats method:

this.facebook.on('getstats', function (data) {

    //  Handle the loaded data here

});

this.facebook.on('getstatsfail', function (error) {

    //  Handle what the game should do if the stats fail to load

});

this.facebook.getStats();

As with all SDK calls, it's asynchronous, so you need to wait for the getstats event before you can act upon it.

If you call getStats with no arguments then it will return every statistic currently saved for that player.

But, if you just want one, or a few, statistics then you can specify that in the call by passing in an array of stat keys. Imagine we just need to know the players current level and race, to know which assets to load to skin our sprites with, we can request just those values:

this.facebook.getStats([ 'level', 'race' ]);

When the call resolves, the event will be handled and given a data object, which will contain two keys level and race, which will have integer values corresponding to their most recently saved values.

Using specific keys allows you to cut down on the amount of data being returned to your game, especially if you're tracking a large number of stats.

Stats are extremely useful, although their 'write-once, saved forever' nature means they are not suitable for transient data, and should instead be considered for values you wish to persist long-term.