Scoreboard API

Games in Catalog have access to the scoreboard feature, posting high scores to our server and fetching them from it. Below you will find documentation for both Lua and C scoreboard APIs.

What games can use the Scoreboard API?

Scoreboard support is only available to games that are distributed via Panic in a Season or in Catalog.

Creating a scoreboard

In order to post scores, your game will need its own scoreboard (with a corresponding scoreboard ID).

Currently, only Panic can create scoreboards. Please contact your Panic representative so we can do this for you.

Your game can have as many scoreboards as you would like, keeping track of various statistics. Boards can be sorted high-to-low or low-to-high, per your specifications.

Scoreboards and caching

The Scoreboards API will always try to retrieve the latest score or scores over Wi-Fi. In the case that network connectivity is not available, it will retrieve the score or scores from the local cache, if available.

Scoreboard performance

Because it can take a while to retrieve scores via Wi-Fi (sometimes 10 seconds or more on device), you could consider pre-fetching high scores if they are an important part of your game experience. (Note that you may be impacting performance of your game in other ways during the fetch period. Depending on your desired game experience, that delay may be more or less acceptable than the one users will encounter if you fetch only on-demand.)

Testing the Scoreboard API

On the Simulator

  • Your Simulator will need to be registered (associated with a user account). If it is not, an error will result upon calling a Scoreboard API. (Scoreboard APIs typically return data that only make sense in the context of the user that is requesting the data.)

On a Playdate

  • IMPORTANT: Make sure to copy your game to your device over USB rather than via the wireless “Sideload” functionality. (Wireless sideload alters the game’s bundle ID, meaning your game will not match up with your registered scoreboards.)

Lua API reference

To use playdate.scoreboards, you must define a valid bundle ID in your PDX metadata. Scoreboards must be created on the Playdate servers.

playdate.scoreboards provides an interface to manage global high scores.

There is an on-device scoreboard cache which keeps track of most recent high scores, and keeps new scores for later submission.

Cacheable results are rerturned with a lastUpdated field, containing the timestamp of the last update represented as the number of seconds since Playdate epoch.

Callbacks are of the form:

scoreboardsCallback(status, result)

where status contains a code field specifying OK or ERROR:

{
	code = "ERROR",
	message = "Some error message"
}

playdate.scoreboards.getScoreboards(callback)

Invokes the given callback with a list of the registered scoreboards. (Note that if you already know the string ID for the scoreboard you want to query, this call is unnecessary.)

{
	lastUpdated = 649972900,
	boards = [
		{
			boardID = "highscores",
			name = "High Scores"
		},
		{
			boardID = "lowscores",
			name = "Low Scores"
		}
	]
}
  • callback: Callback to invoke with the results.

playdate.scoreboards.getScores(boardID, callback)

Invokes the given callback with a list of the top scores on the given board. (Typically ten scores or fewer.) If the current player is not in the top scores, their highest score is given as the last result.

{
	lastUpdated = 649972900,
	scores = [
		{
			rank = 1,
			player = "mario",
			value = 100
		},
		{
			rank = 2,
			player = "luigi",
			value = 20
		}
	]
}
  • boardID: ID of the board to be queried.

  • callback: Callback to be invoked with the results.

playdate.scoreboards.addScore(boardName, value, callback)

Adds a new score to the specified board. Invokes the given callback with the resulting rank for the given value.

If Wi-Fi is not available, the outgoing value will be queued on device and sent to the server on a later attempt. In the case that it is added to the outgoing queue, the result will not specify a rank.

{
	rank = 30,
	player = "mario",
	value = 173
}
  • boardName: Name of the board.
  • value: Integer value to post on the board.
  • callback: Callback to invoke with the results.

playdate.scoreboards.getPersonalBest(boardName, callback)

Gets the player’s personal best score. Invokes the given callback with the score.

This will only operate on locally stored scores. In the event that there is no available high score for this player, the callback will be invoked with nil.

{
	rank = 7,
	player = "wario",
	value = 92
}

C API reference

Note that registered callbacks are responsible for freeing all scores and scoreboard data through the appropriate free functions documented below.

PDScore

typedef struct {
	uint32_t rank;
	uint32 t value:
	char *player;
} PDScore;
  • rank: The rank of this score in the scoreboard.
  • value: The actual score.
  • player: The name of the player who got this score.

PDScoresList

typedef struct {
	char *boardID;
	unsigned int count;
	uint32_t lastUpdated;
	unsigned int playerIncluded;
	unsigned int limit;
	PDScore *scores;
} PDScoresList;
  • boardID: The ID string of the board.
  • count: The number of scores in the scores array.
  • lastUpdated: Timestamp of when we last updated these scores on device.
  • playerincluded: NYI
  • limit: NYI
  • scores: An array of scores, with count entries.

PDBoard

typedef struct {
	char *boardID;
	char *name:
} PDBoard;
  • boardID: The ID string of the board.
  • name: The friendly name of the board.

PDBoardsList

typedef struct {
	unsigned int count;
	uint32_t lastUpdated;
	PDBoard *boards;
} PDBoardsList;
  • count: The number of boards in the boards array.
  • lastUpdated: Timestamp of when we last updated this list on device.
  • boards: An array of scores, with count entries.

Callback Functions

typedef void (*AddScoreCallback) (PDScore *score, const char* errorMessage);
typedef void (*PersonalBestCallback) (PDScore *score, const char errorMessage);
typedef void (*BoardsListCallback) (PDBoardsList *boards, const char *errorMessage);
typedef void (*ScoresCallback) (PDScoresList *scores, const char *errorMessage);

int playdate->scoreboads->addScore(const char *boardID, uint32_t value AddScoreCallback callback)

Adds a score to the specified board. If Wi-Fi is unavailable, adds it to a local outgoing cache. Invokes the callback with the resulting score and rank if Wi-Fi is available.

int playdate->scoreboards->getPersonalBest (const char *boardId, PersonalBestCallback callback)

Get the local player’s top score from the specified scoreboard. The score is returned through the provided callback. If Wi-Fi is unavailable, the players best score may be fetched from a local cache.

void playdate->scoreboards->freeScore(PDScore *score)

Free a score struct that was provided to a callback.

int playdate->scoreboards->getScoreboards (BoardsListCallback callback)

Get the list of scoreboards available to this game. The list is returned through the provided callback. If Wi-Fi is unavailable, the list may be fetched from a local cache.

void playdate->scoreboards->freeBoardsList (PDBoardsList *boardsList)

Free a list of scoreboards.

int playdate-scoreboards-›getScores (const char *boardId, ScoresCallback callback)

Get the top scores for the specified board. (Typically ten or fewer.) The list of scores is returned through the provided callback. The list of scores will always contain the local player if they have any scores on the board. If Wi-Fi is unavailable, the list may be fetched from a local cache.

void playdate->scoreboards->freeScoresList(PDScoresList *scoresList)

Free a list of scores.

If you didn't find an answer above, contact us