이 가이드에서는 C++ SDK에서 Google Play 게임즈 서비스에서 제공하는 스냅샷 API를 사용하여 저장된 게임을 구현하는 방법을 보여줍니다. API는 PgsSnapshotsClient에서 확인할 수 있습니다.
시작하기 전에
- 이 기능에 관한 자세한 내용은 저장된 게임을 참고하세요.
Google Play 서비스 SDK 설정 가이드에 따라, Google Play Games 서비스을 사용하도록 앱을 설치하고 설정합니다.
Google Play Console 가이드의 안내에 따라 게임의 저장된 게임 지원을 정의합니다.
품질 체크리스트에 설명된 권장사항을 숙지합니다.
스냅샷 클라이언트 가져오기
Snapshots API를 사용하려면 먼저 게임에서 PgsSnapshotsClient 핸들을 가져와야 합니다. 이렇게 하려면 PgsSnapshotsClient_create() 메서드를 호출하고 Android 활동을 전달하면 됩니다.
참고: C++ SDK 함수는 콜백을 통해 결과를 비동기적으로 반환합니다.
// 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);
저장된 게임 표시
게임에서 플레이어에게 진행 상황을 저장하거나 복원하는 옵션을 제공할 때마다 Snapshots API를 통합할 수 있습니다.
개발을 간소화하기 위해 스냅샷 API는 기본 저장된 게임 선택 사용자 인터페이스 (UI)를 제공합니다. 이 UI를 실행하려면 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);
저장된 게임 작성
저장된 게임에 콘텐츠를 저장하려면 다음 단계를 따르세요.
PgsSnapshotsClient_open()을 사용하여 스냅샷을 비동기식으로 엽니다. 새 저장 파일을 만들려면create_if_not_found를 true로 지정합니다.- 결과는
PgsSnapshotsClient_OpenCallback에 제공됩니다. 성공하고 충돌이 없으면PgsSnapshot*이 표시됩니다. - 바이트 배열 (
uint8_t*)로 저장할 데이터를 준비합니다. - 저장을 설명하는
PgsSnapshotMetadataChange*객체를 만듭니다. PgsSnapshotsClient_commitAndClose를 호출하여 변경사항을 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 ); }
저장된 게임 로드
저장된 게임을 검색하려면 다음 단계를 따르세요.
PgsSnapshotsClient_open()를 사용하여 이름으로 스냅샷을 비동기식으로 엽니다.PgsSnapshotsClient_OpenCallback에서 성공하면 데이터에 액세스합니다. API는uint8_t*데이터와 크기를 가져오는 방법을 제공하지만PgsSnapshot또는 연결된PgsSnapshotContents에서 바이트를 읽는 방법은 이 문서에 자세히 설명되어 있지 않습니다.// 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 ); }
저장된 게임 충돌 처리
PgsSnapshotsClient_open 콜백이 호출될 때 conflict 매개변수가 NULL이 아니면 충돌이 발생한 것이므로 PgsSnapshotsClient_resolveConflict를 사용하여 충돌을 해결합니다.
/// @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);