快速接入
功能概述
- 排行榜支持开发者自定义维度的排行榜。游戏上报成绩,TapTap 完成成绩计算和排序后,提供排行榜界面或数据供游戏展示。每个排行榜自带总榜与好友榜,并支持永久榜与按周期重置的榜单。
- 更详细的功能介绍请参考排行榜功能介绍。
集成步骤
- 本文档以 C++ 为例演示排行榜集成步骤,其他语言可参考相应的 DLL 调用方式。
- 在集成排行榜之前,请先阅读快速开始了解基本的集成 流程,并完成 SDK 初始化。
调用排行榜任何 API 函数前,必须先成功调用 TapSDK_Init 进行初始化。未初始化或初始化失败时,调用排行榜函数将返回错误或者非预期结果。
1. 上报分数
当玩家产生新成绩时,调用 TapLeaderboard_AsyncSubmitScores() 批量上报。单次最多上报 5 条记录,结果通过 TapEventID::LeaderboardSubmitScores 回调返回:
#include <atomic>
#include <iostream>
#include <thread>
#include "taptap_api.h"
#include "taptap_leaderboard.h"
using namespace std;
atomic<int64_t> gRequestID;
// 上报分数回调函数
void submitScoresCallback(TapEventID eventID, void* data)
{
// 使用 TapLeaderboardSubmitScoresResponse* 强转 data 类型,获取上报分数的结果
// 注意:data 及其里面引用的其他内存,在回调函数返回后会被 SDK 释放。如需长期使用,请开发者自行复制一份
auto resp = static_cast<TapLeaderboardSubmitScoresResponse*>(data);
if (resp->error == nullptr) { // 请求成功
for (uint32_t i = 0; i < resp->result_count; ++i) {
const auto& r = resp->results[i];
if (r.score_result == nullptr) {
continue;
}
// 注意:所有字符串字段(char*)均为 UTF-8 编码,请根据需要自行转换
cout << "submit callback success: requestID=" << resp->request_id
<< ", leaderboard_id=" << r.leaderboard_id
<< ", period_token=" << (r.period_token ? r.period_token : "null")
<< ", raw_score=" << r.score_result->raw_score
<< ", new_best=" << r.score_result->new_best << endl;
}
} else { // 请求失败,处理错误
cout << "submit callback failed, code=" << resp->error->code
<< ", message=" << resp->error->message << endl;
}
}
int main()
{
// 这里省略 SDK 初始化和启动校验相关代码,假设已经正确完成
// 1. 注册上报分数回调函数,只需注册一次
TapSDK_RegisterCallback(TapEventID::LeaderboardSubmitScores, submitScoresCallback);
// 2. 构建上报请求,单次最多 5 条
TapLeaderboardScoreItem items[2];
// 结构体"零值化",避免内存随机值导致的野指针问题
// C++11 及以上,可以使用 TapLeaderboardScoreItem items[2]{};,无需 memset
memset(items, 0, sizeof(items));
// 注意:所有字符串字段(char*)必须使用 UTF-8 编码
items[0].leaderboard_id = "your_leaderboard_id_1"; // 开发者中心配置的排行榜 ID
items[0].score = 1999;
items[1].leaderboard_id = "your_leaderboard_id_2";
items[1].score = 256;
TapLeaderboardSubmitScoresRequest submitRequest;
memset(&submitRequest, 0, sizeof(submitRequest));
submitRequest.item_count = 2;
submitRequest.items = items;
// 3. 发起上报分数的异步请求
auto ret = TapLeaderboard_AsyncSubmitScores(
TapLeaderboard(), // 排行榜模块单例对象
++gRequestID, // 请求 ID,由开发者生成,用于在回调函数中对应到原始请求
&submitRequest);
if (ret != TapSDK_Result_OK) { // 请求发起失败,不会触发回调,请根据返回值做相应处理
cout << "TapLeaderboard_AsyncSubmitScores failed, ret=" << ret << endl;
return -1;
}
// 请求发起成功,等待回调函数返回处理结果
// 4. 游戏主循环
bool running = true;
while (running) {
// 处理 SDK 回调事件
TapSDK_RunCallbacks();
// 您的游戏逻辑
// ...
// 控制帧率,请按游戏实际需求调整
this_thread::sleep_for(chrono::milliseconds(100));
}
// 5. 清理资源
TapSDK_Shutdown();
return 0;
}
2. 申请好友信息授权(使用好友榜时)
仅当游戏需要使用好友榜(collection = TapLeaderboardCollection_Friends)时才需要执行本步骤。在拉取或展示好友榜前,建议先调用 TapUser_AsyncGetApprovedScopes() 查询用户当前已授权范围,仅当 user_friends 不在已授权范围内时,再调用 TapUser_AsyncAuthorize("user_friends") 申请好友信息授权,避免重复弹窗打扰用户。未授权时调用好友榜相关接口将返回授权错误。已授权范围查询结果通过 TapEventID::UserGetApprovedScopes 回调返回,授权完成事件通过 TapEventID::AuthorizeFinished 回调返回。相关 API 详见 TapUser_AsyncGetApprovedScopes 与 TapUser_AsyncAuthorize。
#include <atomic>
#include <cstring>
#include <iostream>
#include <thread>
#include "taptap_api.h"
using namespace std;
// 发起 user_friends 授权请求
void requestUserFriendsAuthorize()
{
auto ret = TapUser_AsyncAuthorize("user_friends");
switch (ret) {
case TapUser_AsyncAuthorize_Result::OK:
cout << "authorize request sent, waiting for user confirmation" << endl;
break;
case TapUser_AsyncAuthorize_Result::InFlight:
cout << "authorize already in progress, please wait" << endl;
break;
case TapUser_AsyncAuthorize_Result::Failed:
cout << "TapUser_AsyncAuthorize failed, please retry" << endl;
break;
case TapUser_AsyncAuthorize_Result::Unknown:
cout << "authorize failed, please check SDK init state" << endl;
break;
}
}
// 获取已授权范围回调函数
void getApprovedScopesCallback(TapEventID eventID, void* data)
{
// 使用 TapUserGetApprovedScopesResponse* 强转 data 类型,获取已授权范围
auto resp = static_cast<TapUserGetApprovedScopesResponse*>(data);
if (resp->error != nullptr) {
cout << "get approved scopes failed, code=" << resp->error->code
<< ", message=" << resp->error->message << endl;
return;
}
// 检查 user_friends 是否已授权
bool hasUserFriends = false;
for (uint32_t i = 0; i < resp->scope_count; ++i) {
if (strcmp(resp->scopes[i], "user_friends") == 0) {
hasUserFriends = true;
break;
}
}
if (hasUserFriends) {
cout << "user_friends already approved, no need to request again" << endl;
// 已授权,可直接调用好友榜相关接口(collection = TapLeaderboardCollection_Friends)
} else {
cout << "user_friends not approved, requesting authorize" << endl;
requestUserFriendsAuthorize();
}
}
// 授权完成回调函数
void authorizeFinishedCallback(TapEventID eventID, void* data)
{
// 使用 AuthorizeFinishedResponse* 强转 data 类型,获取授权结果
auto resp = static_cast<AuthorizeFinishedResponse*>(data);
if (resp->is_cancel) {
cout << "authorize cancelled by user" << endl;
return;
}
if (resp->error[0] != '\0') {
cout << "authorize failed, error=" << resp->error << endl;
return;
}
// 注意:所有字符串字段(char*)均为 UTF-8 编码,请根据需要自行转换
cout << "authorize success, scope=" << resp->scope << endl;
// 此后即可调用好友榜相关接口(collection = TapLeaderboardCollection_Friends)
}
int main()
{
// 这里省略 SDK 初始化和启动校验相关代码,假设已经正确完成
// 1. 注册回调函数,只需注册一次
TapSDK_RegisterCallback(TapEventID::UserGetApprovedScopes, getApprovedScopesCallback);
TapSDK_RegisterCallback(TapEventID::AuthorizeFinished, authorizeFinishedCallback);
// 2. 查询当前已授权范围;仅当 user_friends 缺失时,回调中再发起授权
int64_t requestID = 1; // 开发者自行生成,用于关联请求与回调
auto ret = TapUser_AsyncGetApprovedScopes(requestID);
if (ret != TapSDK_Result_OK) {
cout << "TapUser_AsyncGetApprovedScopes failed, code=" << ret << endl;
return -1;
}
// 3. 游戏主循环
bool running = true;
while (running) {
TapSDK_RunCallbacks();
// 您的游戏逻辑
// ...
this_thread::sleep_for(chrono::milliseconds(100));
}
// 4. 清理资源
TapSDK_Shutdown();
return 0;
}
3. 拉取榜单数据
调用 TapLeaderboard_AsyncLoadScores() 拉取指定排行榜的成绩列表。支持总榜 / 好友榜切换、按周期查询和分页。结果通过 TapEventID::LeaderboardLoadScores 回调返回:
#include <atomic>
#include <iostream>
#include <thread>
#include "taptap_api.h"
#include "taptap_leaderboard.h"
using namespace std;
atomic<int64_t> gRequestID;
// 拉取榜单数据回调函数
void loadScoresCallback(TapEventID eventID, void* data)
{
// 使用 TapLeaderboardLoadScoresResponse* 强转 data 类型,获取榜单数据
// 注意:data 及其里面引用的其他内存,在回调函数返回后会被 SDK 释放。如需长期使用,请开发者自行复制一份
auto resp = static_cast<TapLeaderboardLoadScoresResponse*>(data);
if (resp->error == nullptr) { // 请求成功
if (resp->leaderboard != nullptr) {
cout << "load callback success: leaderboard=" << resp->leaderboard->name
<< ", score_count=" << resp->score_count
<< ", is_truncated=" << resp->is_truncated << endl;
}
for (uint32_t i = 0; i < resp->score_count; ++i) {
const auto& s = resp->scores[i];
// 注意:所有字符串字段(char*)均为 UTF-8 编码,请根据需要自行转换
cout << " rank=" << s.rank
<< ", user=" << (s.user.name ? s.user.name : "null")
<< ", score=" << s.score << endl;
}
// 分页:is_truncated 为 true 时,将 continuation_token 复制后传给下一次请求即可拉取下一页
} else { // 请求失败,处理错误
cout << "load callback failed, code=" << resp->error->code
<< ", message=" << resp->error->message << endl;
}
}
int main()
{
// 这里省略 SDK 初始化和启动校验相关代码,假设已经正确完成
// 1. 注册拉取榜单数据回调函数,只需注册一次
TapSDK_RegisterCallback(TapEventID::LeaderboardLoadScores, loadScoresCallback);
// 2. 构建拉取榜单数据的请求
TapLeaderboardLoadScoresRequest loadRequest;
// 结构体"零值化",避免内存随机值导致的野指针问题
// C++11 及以上,可以使用 TapLeaderboardLoadScoresRequest loadRequest{};,无需 memset
memset(&loadRequest, 0, sizeof(loadRequest));
// 注意:所有字符串字段(char*)必须使用 UTF-8 编码
loadRequest.leaderboard_id = "your_leaderboard_id"; // 开发者中心配置的排行榜 ID
loadRequest.collection = TapLeaderboardCollection_Public; // 总榜;好友榜传 TapLeaderboardCollection_Friends
loadRequest.continuation_token = nullptr; // 首次拉取传 NULL;分页时传上一次回调返回的 token
loadRequest.period_token = nullptr; // 当前周期;查历史周期请传对应 token
// 3. 发起拉取榜单数据的异步请求
auto ret = TapLeaderboard_AsyncLoadScores(
TapLeaderboard(), // 排行榜模块单例对象
++gRequestID, // 请求 ID,由开发者生成,用于在回调函数中对应到原始请求
&loadRequest);
if (ret != TapSDK_Result_OK) { // 请求发起失败,不会触发回调,请根据返回值做相应处理
cout << "TapLeaderboard_AsyncLoadScores failed, ret=" << ret << endl;
return -1;
}
// 请求发起成功,等待回调函数返回处理结果
// 4. 游戏主循环
bool running = true;
while (running) {
TapSDK_RunCallbacks();
// 您的游戏逻辑
// ...
this_thread::sleep_for(chrono::milliseconds(100));
}
// 5. 清理资源
TapSDK_Shutdown();
return 0;
}
4. 拉取当前用户排名
调用 TapLeaderboard_AsyncLoadMyScores() 仅拉取当前登录用户在指定排行榜上的成绩与排名。结果通过 TapEventID::LeaderboardLoadMyScores 回调返回:
#include <atomic>
#include <iostream>
#include <thread>
#include "taptap_api.h"
#include "taptap_leaderboard.h"
using namespace std;
atomic<int64_t> gRequestID;
// 拉取当前用户排名回调函数
void loadMyScoresCallback(TapEventID eventID, void* data)
{
// 使用 TapLeaderboardLoadMyScoresResponse* 强转 data 类型,获取当前用户排名
// 注意:data 及其里面引用的其他内存,在回调函数返回后会被 SDK 释放。如需长期使用,请开发者自行复制一份
auto resp = static_cast<TapLeaderboardLoadMyScoresResponse*>(data);
if (resp->error == nullptr) { // 请求成功
if (resp->score == nullptr) {
cout << "load my scores callback success: user not on leaderboard" << endl;
} else {
const auto& s = *resp->score;
// 注意:所有字符串字段(char*)均为 UTF-8 编码,请根据需要自行转换
cout << "load my scores callback success: rank=" << s.rank
<< ", score=" << s.score << endl;
}
} else { // 请求失败,处理错误
cout << "load my scores callback failed, code=" << resp->error->code
<< ", message=" << resp->error->message << endl;
}
}
int main()
{
// 这里省略 SDK 初始化和启动校验相关代码,假设已经正确完成
// 1. 注册拉取当前用户排名回调函数,只需注册一次
TapSDK_RegisterCallback(TapEventID::LeaderboardLoadMyScores, loadMyScoresCallback);
// 2. 构建拉取当前用户排名的请求
TapLeaderboardLoadMyScoresRequest myRequest;
memset(&myRequest, 0, sizeof(myRequest));
// 注意:所有字符串字段(char*)必须使用 UTF-8 编码
myRequest.leaderboard_id = "your_leaderboard_id";
myRequest.collection = TapLeaderboardCollection_Public; // 总榜 / 好友榜
myRequest.period_token = nullptr; // 当前周期;查历史周期请传对应 token
// 3. 发起拉取当前用户排名的异步请求
auto ret = TapLeaderboard_AsyncLoadMyScores(
TapLeaderboard(), // 排行榜模块单例对象
++gRequestID, // 请求 ID,由开发者生成,用于在回调函数中对应到原始请求
&myRequest);
if (ret != TapSDK_Result_OK) {
cout << "TapLeaderboard_AsyncLoadMyScores failed, ret=" << ret << endl;
return -1;
}
// 请求发起成功,等待回调函数返回处理结果
// 4. 游戏主循环
bool running = true;
while (running) {
TapSDK_RunCallbacks();
// 您的游戏逻辑
// ...
this_thread::sleep_for(chrono::milliseconds(100));
}
// 5. 清理资源
TapSDK_Shutdown();
return 0;
}
5. 获取用户相近分数
调用 TapLeaderboard_AsyncLoadMyCenteredScores() 获取一段用户相近分数,常用于"我的附近排名"展示。结果通过 TapEventID::LeaderboardLoadMyCenteredScores 回调返回:
#include <atomic>
#include <iostream>
#include <thread>
#include "taptap_api.h"
#include "taptap_leaderboard.h"
using namespace std;
atomic<int64_t> gRequestID;
// 获取用户相近分数回调函数
void loadMyCenteredScoresCallback(TapEventID eventID, void* data)
{
// 使用 TapLeaderboardLoadMyCenteredScoresResponse* 强转 data 类型,获取榜单数据
// 注意:data 及其里面引用的其他内存,在回调函数返回后会被 SDK 释放。如需长期使用,请开发者自行复制一份
auto resp = static_cast<TapLeaderboardLoadMyCenteredScoresResponse*>(data);
if (resp->error == nullptr) { // 请求成功
cout << "centered callback success, score_count=" << resp->score_count << endl;
for (uint32_t i = 0; i < resp->score_count; ++i) {
const auto& s = resp->scores[i];
// 注意:所有字符串字段(char*)均为 UTF-8 编码,请根据需要自行转换
cout << " rank=" << s.rank
<< ", user=" << (s.user.name ? s.user.name : "null")
<< ", score=" << s.score << endl;
}
} else { // 请求失败,处理错误
cout << "centered callback failed, code=" << resp->error->code
<< ", message=" << resp->error->message << endl;
}
}
int main()
{
// 这里省略 SDK 初始化和启动校验相关代码,假设已经正确完成
// 1. 注册获取用户相近分数回调函数,只需注册一次
TapSDK_RegisterCallback(TapEventID::LeaderboardLoadMyCenteredScores, loadMyCenteredScoresCallback);
// 2. 构建请求
TapLeaderboardLoadMyCenteredScoresRequest centeredRequest;
memset(¢eredRequest, 0, sizeof(centeredRequest));
centeredRequest.leaderboard_id = "your_leaderboard_id";
centeredRequest.collection = TapLeaderboardCollection_Public;
centeredRequest.max_results = 21; // 含当前用户共返回 21 条;0 表示服务端默认值
// 3. 发起异步请求
auto ret = TapLeaderboard_AsyncLoadMyCenteredScores(
TapLeaderboard(),
++gRequestID,
¢eredRequest);
if (ret != TapSDK_Result_OK) {
cout << "TapLeaderboard_AsyncLoadMyCenteredScores failed, ret=" << ret << endl;
return -1;
}
// 请求发起成功,等待回调函数返回处理结果
// 4. 游戏主循环
bool running = true;
while (running) {
TapSDK_RunCallbacks();
// 您的游戏逻辑
// ...
this_thread::sleep_for(chrono::milliseconds(100));
}
// 5. 清理资源
TapSDK_Shutdown();
return 0;
}
6. 打开排行榜页面
调用 TapLeaderboard_ShowLeaderboards() 在 TapTap 内打开排行榜展示页。该接口为同步调用,无需等待回调:
#include <iostream>
#include "taptap_api.h"
#include "taptap_leaderboard.h"
using namespace std;
int main()
{
// 这里省略 SDK 初始化和启动校验相关代码,假设已经正确完成
TapLeaderboardShowRequest showRequest;
memset(&showRequest, 0, sizeof(showRequest));
// 注意:所有字符串字段(char*)必须使用 UTF-8 编码
showRequest.leaderboard_id = "your_leaderboard_id";
showRequest.collection = TapLeaderboardCollection_Public; // 默认展示总榜
auto ret = TapLeaderboard_ShowLeaderboards(TapLeaderboard(), &showRequest);
if (ret != TapSDK_Result_OK) { // 打开失败,请根据返回值做相应处理
cout << "TapLeaderboard_ShowLeaderboards failed, ret=" << ret << endl;
return -1;
}
TapSDK_Shutdown();
return 0;
}
错误码
- 接口调用返回值均为
TapSDK_Result,可根据该值做提示或重试。详见TapSDK_Result。- 返回值非
TapSDK_Result_OK时,表示请求发起失败,后续不会触发回调。
- 返回值非
- 回调函数中
resp->error非空时,表示请求失败,可根据TapSDK_ErrorCode做提示或重试。详见TapSDK_ErrorCode。