Ce guide explique comment implémenter des Jeux enregistrés à l'aide de l'API Snapshots fournie par les services Google Play Games dans le SDK C++. Les API se trouvent
dans PgsSnapshotsClient.
Avant de commencer
- Pour en savoir plus sur cette fonctionnalité, consultez Jeux enregistrés.
Suivez les instructions disponibles dans le guide Configurer le SDK des services Google Play afin d'installer et de configurer votre application pour qu'elle utilise les services Google Play Games.
Définissez la prise en charge des jeux enregistrés pour votre jeu en suivant les instructions du guide de la Google Play Console.
Familiarisez-vous avec les recommandations décrites dans la checklist de contrôle qualité.
Obtenir le client Snapshots
Pour commencer à utiliser l'API Snapshots, votre jeu doit d'abord obtenir un
PgsSnapshotsClient descripteur. Pour ce faire, appelez la méthode
PgsSnapshotsClient_create() et transmettez l'activité Android.
Remarque : Les fonctions du SDK C++ renvoient des résultats de manière asynchrone via des rappels.
// Assuming 'android_activity' is a jobject referencing your Android Activity PgsSnapshotsClient* snapshots_client = PgsSnapshotsClient_create(android_activity); // ... use the client ... // When done, destroy the client to free resources // PgsSnapshotsClient_destroy(snapshots_client);
Afficher les jeux enregistrés
Vous pouvez intégrer l'API Snapshots partout où votre jeu offre aux joueurs la possibilité d'enregistrer ou de restaurer leur progression.
Pour simplifier le développement, l'API Snapshots fournit une interface utilisateur (UI) de sélection de jeux enregistrés par défaut. Pour lancer cette interface utilisateur, appelez
PgsSnapshotsClient_showSelectSnapshotUI.
// Callback function to handle the result of showing the UI void OnShowSavedGamesUI(PgsStatusCode status_code, void* user_data) { if (status_code == PGS_STATUS_SUCCESS) { // UI was shown successfully. The player can now interact with it. // The game doesn't receive direct data back from this callback about // which snapshot was selected. Your game should typically provide options // to load or open snapshots by name after the UI is dismissed. } else { // Handle error or failure to show UI } } // Function to show the default Saved Games UI void ShowSavedGamesUI(PgsSnapshotsClient* client, jobject activity) { const char* title = "See My Saves"; bool allow_add_button = true; bool allow_delete_button = true; int max_snapshots = 5; PgsSnapshotsClient_showSelectSnapshotUI( client, activity, title, allow_add_button, allow_delete_button, max_snapshots, OnShowSavedGamesUI, NULL // user_data ); } // Example usage: // ShowSavedGamesUI(snapshots_client, android_activity);
Écrire des jeux enregistrés
Pour stocker du contenu dans un jeu enregistré :
- Ouvrez un instantané de manière asynchrone à l'aide de
PgsSnapshotsClient_open(). Spécifiezcreate_if_not_foundcomme étant "true" si vous souhaitez créer un nouvel enregistrement. - Le résultat est fourni dans le
PgsSnapshotsClient_OpenCallback. En cas de réussite et en l'absence de conflit, vous recevrez unPgsSnapshot*. - Préparez les données que vous souhaitez enregistrer sous forme de tableau d'octets (
uint8_t*). - Créez un
PgsSnapshotMetadataChange*objet pour décrire l'enregistrement. Appelez
PgsSnapshotsClient_commitAndClosepour envoyer les modifications aux serveurs de Google.// Callback for commitAndClose void OnSnapshotCommitted(PgsStatusCode status_code, PgsSnapshotMetadata* metadata, void* user_data) { if (status_code == PGS_STATUS_SUCCESS) { // Save successful if (metadata) { // Metadata for the committed snapshot PgsSnapshotMetadata_Release(metadata); } } else { // Handle error } } // Function to write data to a snapshot void WriteSnapshot(PgsSnapshotsClient* client, PgsSnapshot* snapshot, const uint8_t* data, size_t data_size, const char* description /*, Bitmap coverImage */) { PgsSnapshotMetadataChange* metadataChange = NULL; // Placeholder // Commit the operation PgsSnapshotsClient_commitAndClose( client, snapshot, metadataChange, data, data_size, OnSnapshotCommitted, NULL // user_data ); // if (metadataChange) PgsSnapshotMetadataChange_Release(metadataChange); } // Callback for opening the snapshot before writing void OnSnapshotOpenForWrite(PgsStatusCode status_code, PgsSnapshot* snapshot, PgsSnapshotConflict* conflict, void* user_data) { if (status_code == PGS_STATUS_SUCCESS) { if (snapshot) { // Successfully opened/created. Now write to it. const char* save_data_str = "MY_GAME_SAVE_DATA"; const uint8_t* data = (const uint8_t*)save_data_str; size_t data_size = strlen(save_data_str); WriteSnapshot((PgsSnapshotsClient*)user_data, snapshot, data, data_size, "My Save Description"); // PgsSnapshot_destroy(snapshot) is likely called after commitAndClose by the SDK } else if (conflict) { // Handle conflict before writing, or open with a policy that auto-resolves. PgsSnapshotConflict_destroy(conflict); } } else { // Handle error opening } } // Example: Open and write to a snapshot void OpenAndWriteExample(PgsSnapshotsClient* client, const char* snapshot_name) { PgsSnapshotsClient_open( client, snapshot_name, true, // create_if_not_found kPgsSnapshotConflictPolicyManual, // Or another policy OnSnapshotOpenForWrite, client // user_data ); }
Charger des jeux enregistrés
Pour récupérer les jeux enregistrés :
- Ouvrez l'instantané de manière asynchrone par son nom à l'aide de
PgsSnapshotsClient_open(). Dans
PgsSnapshotsClient_OpenCallback, en cas de réussite, accédez aux données. L'API permet d'obtenir lesuint8_t*données et la taille, bien que la méthode de lecture des octets à partir dePgsSnapshotou d'unPgsSnapshotContentsassocié ne soit pas détaillée dans ce document.// Assuming functions exist to read data from PgsSnapshotContents // For example, PgsSnapshotContents* PgsSnapshot_getContents(PgsSnapshot* snapshot); // For example, bool PgsSnapshotContents_readFully(PgsSnapshotContents* contents, uint8_t** out_data, size_t* out_size); // For example, void PgsSnapshotContents_releaseData(uint8_t* data); void OnSnapshotOpenForRead(PgsStatusCode status_code, PgsSnapshot* snapshot, PgsSnapshotConflict* conflict, void* user_data) { if (status_code == PGS_STATUS_SUCCESS) { if (snapshot) { // Successfully opened. Now read from it. // THE FOLLOWING IS HYPOTHETICAL based on common patterns: // PgsSnapshotContents* contents = PgsSnapshot_getContents(snapshot); // uint8_t* data = NULL; // size_t data_size = 0; // if (contents && PgsSnapshotContents_readFully(contents, &data, &data_size)) { // // Successfully read data // Log("Snapshot data loaded, size: %zu", data_size); // ... process data ... // PgsSnapshotContents_releaseData(data); // } // PgsSnapshotContents_destroy(contents); // If necessary PgsSnapshot_destroy(snapshot); } else if (conflict) { // Handle conflict Log("Snapshot open resulted in a conflict."); PgsSnapshotConflict_destroy(conflict); } } else { // Handle error opening Log("Error while opening Snapshot: %d", status_code); } } // Example: Load a specific saved game void LoadSnapshotByName(PgsSnapshotsClient* client, const char* snapshot_name) { int conflictResolutionPolicy = kPgsSnapshotConflictPolicyMostRecentlyModified; PgsSnapshotsClient_open( client, snapshot_name, false, // create_if_not_found conflictResolutionPolicy, OnSnapshotOpenForRead, NULL // user_data ); }
Gérer les conflits liés aux jeux enregistrés
Lorsque le rappel PgsSnapshotsClient_open est appelé, si le paramètre conflict
n'est pas NULL, un conflit s'est produit. Utilisez
PgsSnapshotsClient_resolveConflict pour résoudre le conflit.
/// @brief Asynchronously resolves a snapshot conflict. /// /// @param snapshots_client The client handle. /// @param conflict_id The ID of the conflict to resolve. /// @param snapshot_id The ID of the snapshot to use for resolution. /// @param metadata_change The metadata changes to apply to the snapshot, or /// NULL for no changes. /// @param contents The contents to resolve the conflict with. /// @param callback Function to be called with result of asynchronous /// operation. See PgsSnapshotsClient_OpenCallback. /// @param user_data Arbitrary data pointer to be passed back to callback. void PgsSnapshotsClient_resolveConflict( PgsSnapshotsClient* snapshots_client, const char* conflict_id, const char* snapshot_id, PgsSnapshotMetadataChange* metadata_change, PgsSnapshotContents* contents, PgsSnapshotsClient_OpenCallback callback, void* user_data);