Skip to content

Leaderboards

The Scorbit SDK provides functionality to retrieve leaderboard data, allowing you to display top scores and show where a specific score ranks among other players.

Global vs. Local

All game titles have both a global leaderboard and a local one. Thanks to Scorbit, owners of games no longer run out of ranking to climb after they get the Grand Champion of their own game. Local leaderboards also come in different flavors, and it is not uncommon for a venue owner or a player to create custom local leaderboards for things like leagues and local competitions.

One Score Per Player or All Scores

One type of leaderboard that is very popular filters the result so only the highest score per any single player is displayed. This allows more individuals onto a more diverse leaderboard and maintains legitimacy. A single, heavy player can't take up all the positions.

Score Context

In some cases, if a global leaderboard is large, rather than just display the top 10 or 20 scores, you may wish to show the score "in context," with the scores ranking just above and just below the desired score. For example, for a score that ranks 1500 out of 3000, you may want to show scores 1490 through 1510, to show where a player ranks on the larger list. This gives every player a position on an infinite leaderboard!

Requesting Scores

You can request leaderboard data with an optional score context filter:

void request_leaderboard(sb_game_handle_t state, sb_score_t score_filter) {
    // Request top scores around the filter score
    sb_request_top_scores(state, score_filter, leaderboard_callback, NULL);
}

void leaderboard_callback(sb_error_t error, const char* scores_json, void* user_data) {
    if (error == SB_EC_SUCCESS) {
        // Handle the leaderboard data (in JSON format)
        display_leaderboard(scores_json);
    } else if (error == SB_EC_NOT_PAIRED) {
        // Handle unpaired device error
        handle_unpaired_error();
    } else if (error == SB_EC_API_ERROR) {
        // Handle API error
        handle_api_error();
    }
}
void request_leaderboard(scorbit::GameState& gs, sb_score_t score_filter) {
    // Request top scores around the filter score
    gs.requestTopScores(score_filter, 
        [](scorbit::Error error, const std::string& scores_json) {
            if (error == scorbit::Error::Success) {
                // Handle the leaderboard data (in JSON format)
                display_leaderboard(scores_json);
            } else if (error == scorbit::Error::NotPaired) {
                // Handle unpaired device error
                handle_unpaired_error();
            } else if (error == scorbit::Error::ApiError) {
                // Handle API error
                handle_api_error();
            }
        });
}
def request_leaderboard(gs, score_filter):
    # Request top scores around the filter score
    gs.request_top_scores(score_filter, lambda error, reply: 
        print(f"Top scores: {reply}" if error == 0 else f"Error: {error}")
    )

Score Filtering

The score filter allows you to see scores in context: - If filter is 0: Returns the overall top scores - If filter has a value: Returns scores above and below the filter value

Usage Examples

Getting Top Scores

// Get the overall leaderboard
sb_request_top_scores(state, 0, leaderboard_callback, NULL);
// Get the overall leaderboard
gs.requestTopScores(0, [](scorbit::Error error, const std::string& scores_json) {
    if (error == scorbit::Error::Success) {
        display_leaderboard(scores_json);
    }
});
# Get the overall leaderboard
gs.request_top_scores(0, lambda error, reply: 
    print(f"Top scores: {reply}" if error == 0 else f"Error: {error}")
)

Getting Contextual Scores

// Get scores around 1,000,000 points
sb_request_top_scores(state, 1000000, leaderboard_callback, NULL);
// Get scores around 1,000,000 points
gs.requestTopScores(1000000, [](scorbit::Error error, const std::string& scores_json) {
    if (error == scorbit::Error::Success) {
        display_leaderboard(scores_json);
    }
});
# Get scores around 1,000,000 points
gs.request_top_scores(1000000, lambda error, reply: 
    print(f"Top scores: {reply}" if error == 0 else f"Error: {error}")
)

Asynchronous Operation

The callback is invoked asynchronously when the operation completes. Use appropriate thread safety measures when handling the response.

Device Pairing

Leaderboard requests require the device to be paired. Check pairing status before requesting scores.

Score Context

Use score filtering to show players where they rank compared to nearby scores.

Best Practices

Request Timing

  • Request leaderboards during appropriate game states
  • Avoid excessive requests
  • Consider caching results

Error Handling

  • Check for pairing status
  • Handle API errors gracefully
  • Provide user feedback

Display

  • Show loading indicators during requests
  • Format scores consistently
  • Highlight the filtered score when displayed