Skip to main content
Version: v4

Quick Start

Overview

  • The Achievement System lets players earn achievements for completing specific goals in the game, boosting engagement and retention. It supports standard achievements, incremental achievements, hidden achievements, and platinum achievements.
  • For a more detailed feature overview, see Achievement System Features.

Integration

  • This guide uses C++ to demonstrate achievement system integration; other languages can refer to the corresponding DLL calling methods.
  • Before integrating the achievement system, read Quick Start to understand the basic integration process, and complete SDK initialization and launch verification.
Initialization Requirement

You must successfully call TapSDK_Init before calling any Achievement API. Calling achievement functions without initialization or after initialization failure will return errors or unexpected results.

1. Unlock an Achievement

When a player meets the criteria for an achievement, call TapAchievement_AsyncUnlock(). The result is returned via the TapEventID::AchievementUnlock callback:

#include <atomic>
#include <iostream>
#include <thread>

#include "taptap_achievement.h"

using namespace std;

atomic<int64_t> gRequestID;

// Unlock achievement callback
void unlockCallback(TapEventID eventID, void* data)
{
if (!data) return; // Guard against null data
// Note: data and its referenced memory are freed by the SDK after the callback returns;
// copy if you need to keep it
auto resp = static_cast<TapAchievementUnlockResponse*>(data);
if (resp->error == nullptr) { // Unlock succeeded
if (resp->achievement != nullptr) { // Check achievement is non-null before dereferencing
const auto& achievement = *resp->achievement;
// Note: all string fields (char*) are UTF-8 encoded; convert as needed
cout << "unlock callback success: id=" << achievement.id
<< ", name=" << achievement.name
<< ", current_steps=" << achievement.current_steps
<< ", newly_unlocked=" << achievement.newly_unlocked << endl;
}
// Only dereference platinum_achievement when it is non-null
if (resp->platinum_achievement != nullptr) {
const auto& platinum = *resp->platinum_achievement;
cout << "platinum unlocked: id=" << platinum.id
<< ", newly_unlocked=" << platinum.newly_unlocked << endl;
}
} else { // Unlock failed — handle the error
cout << "unlock callback failed, code=" << resp->error->code
<< ", message=" << resp->error->message << endl;
}
}

int main()
{
// Assume TapSDK_Init has completed successfully

// 1. Register the unlock callback — only needs to be done once
TapSDK_RegisterCallback(TapEventID::AchievementUnlock, unlockCallback);

// 2. Build the unlock request
TapAchievementUnlockRequest req;
// Zero-initialize the struct to avoid wild pointers from uninitialized memory
// In C++11 or later, you can use TapAchievementUnlockRequest req{}; instead of memset
memset(&req, 0, sizeof(req));
// Note: all string fields (char*) must be UTF-8 encoded
req.achievement_id = "your_achievement_id"; // Achievement ID configured in the Developer Center

// 3. Start the async unlock request
auto ret = TapAchievement_AsyncUnlock(
TapAchievement(), // Achievement module singleton
++gRequestID, // Request ID generated by the developer; echoed in the callback
&req);
if (ret != TapSDK_Result_OK) { // Request failed to start; no callback will be invoked
cout << "TapAchievement_AsyncUnlock failed, ret=" << ret << endl;
return -1;
}

// Request started successfully — wait for the callback

// 4. Main game loop
bool running = true;
while (running) {
// Process SDK callback events
TapSDK_RunCallbacks();
// Your game logic
// ...

// Adjust sleep duration to match your target frame rate
this_thread::sleep_for(chrono::milliseconds(100));
}

// 5. Clean up
TapSDK_Shutdown();
return 0;
}
info

Calling unlock on an already-unlocked achievement does not create a duplicate server record; achievement->newly_unlocked will be false in the callback.

2. Increment Steps for an Incremental Achievement

For incremental achievements that require multiple steps, call TapAchievement_AsyncIncrement() to add steps. The SDK accumulates the total automatically. When the threshold is reached, the achievement unlocks and achievement->newly_unlocked is true in the callback:

#include <atomic>
#include <iostream>
#include <thread>

#include "taptap_achievement.h"

using namespace std;

atomic<int64_t> gRequestID;

// Increment steps callback
void incrementCallback(TapEventID eventID, void* data)
{
if (!data) return; // Guard against null data
// Note: data and its referenced memory are freed by the SDK after the callback returns;
// copy if you need to keep it
auto resp = static_cast<TapAchievementIncrementResponse*>(data);
if (resp->error == nullptr) { // Steps incremented successfully
if (resp->achievement != nullptr) { // Check achievement is non-null before dereferencing
const auto& achievement = *resp->achievement;
// Note: all string fields (char*) are UTF-8 encoded; convert as needed
cout << "increment callback success: id=" << achievement.id
<< ", name=" << achievement.name
<< ", current_steps=" << achievement.current_steps
<< ", newly_unlocked=" << achievement.newly_unlocked << endl;
}
// Only dereference platinum_achievement when it is non-null
if (resp->platinum_achievement != nullptr) {
const auto& platinum = *resp->platinum_achievement;
cout << "platinum unlocked: id=" << platinum.id
<< ", newly_unlocked=" << platinum.newly_unlocked << endl;
}
} else { // Increment failed — handle the error
cout << "increment callback failed, code=" << resp->error->code
<< ", message=" << resp->error->message << endl;
}
}

int main()
{
// Assume TapSDK_Init has completed successfully

// 1. Register the increment callback — only needs to be done once
TapSDK_RegisterCallback(TapEventID::AchievementIncrement, incrementCallback);

// 2. Build the increment request
TapAchievementIncrementRequest req;
// Zero-initialize the struct to avoid wild pointers from uninitialized memory
// In C++11 or later, you can use TapAchievementIncrementRequest req{}; instead of memset
memset(&req, 0, sizeof(req));
// Note: all string fields (char*) must be UTF-8 encoded
req.achievement_id = "your_achievement_id"; // Achievement ID configured in the Developer Center
req.steps = 1; // Number of steps to add

// 3. Start the async increment request
auto ret = TapAchievement_AsyncIncrement(
TapAchievement(), // Achievement module singleton
++gRequestID, // Request ID generated by the developer; echoed in the callback
&req);
if (ret != TapSDK_Result_OK) { // Request failed to start; no callback will be invoked
cout << "TapAchievement_AsyncIncrement failed, ret=" << ret << endl;
return -1;
}

// Request started successfully — wait for the callback

// 4. Main game loop
bool running = true;
while (running) {
// Process SDK callback events
TapSDK_RunCallbacks();
// Your game logic
// ...

// Adjust sleep duration to match your target frame rate
this_thread::sleep_for(chrono::milliseconds(100));
}

// 5. Clean up
TapSDK_Shutdown();
return 0;
}
info

Steps can only increase — they cannot be reduced or reset. Calling this on a non-incremental achievement returns an error in the callback.

3. Show the Achievements Page

Call TapAchievement_ShowAchievements() to open the achievements page. This is a synchronous call — no callback or request ID is needed:

#include <iostream>

#include "taptap_achievement.h"

using namespace std;

int main()
{
// Assume TapSDK_Init has completed successfully

auto ret = TapAchievement_ShowAchievements(TapAchievement());
if (ret != TapSDK_Result_OK) { // Failed to open — handle the return value accordingly
cout << "TapAchievement_ShowAchievements failed, ret=" << ret << endl;
return -1;
}

TapSDK_Shutdown();
return 0;
}

Error Handling

  • All API calls return TapSDK_Result; use it for user feedback or retry. See TapSDK_Result.
    • If the return value is not TapSDK_Result_OK, the request failed to start and no callback will be invoked.
  • When resp->error is non-null in a callback, the request failed; use TapSDK_ErrorCode for feedback or retry. See TapSDK_ErrorCode.