Dodawanie zapisanych gier do gry

Po wycofaniu interfejsu Google Sign-In API w 2026 roku usuniemy pakiet SDK do gier w wersji 1. Z końcem lutego 2025 r. nie będzie już można publikować w Google Play nowych tytułów, w których zastosowano integrację z wersją 1 pakietu SDK gier. Zamiast tego zalecamy używanie pakietu SDK do gier w wersji 2.
Dotychczasowe tytuły z integracjami gier w wersji 1 będą działać jeszcze przez kilka lat, ale zachęcamy do przejścia na wersję 2 od czerwca 2025 r.
Ten przewodnik dotyczy korzystania z pakietu SDK usług gier Play w wersji 1. Pakiet C++ SDK usług gier Play w wersji 2 nie jest jeszcze dostępny.

Z tego przewodnika dowiesz się, jak zapisywać i wczytywać dane o postępach gracza w grze za pomocą usługi Zapisane gry w aplikacji w C++. Możesz używać tej usługi do automatycznego wczytywania i zapisywania postępów gracza w dowolnym momencie rozgrywki. Ta usługa może też umożliwiać graczom wywoływanie interfejsu użytkownika w celu zaktualizowania lub przywrócenia istniejącego zapisu gry albo utworzenia nowego.

Zanim zaczniesz

Jeśli jeszcze tego nie zrobiono, warto zapoznać się z koncepcjami gier zapisanych.

Zanim zaczniesz pisać kod z użyciem interfejsu Saved Games API:

Formaty danych i zgodność z różnymi platformami

Dane zapisanych gier, które zapisujesz na serwerach Google, muszą być w formacie std::vector<uint8_t>. Usługa Zapisane gry dba o kodowanie danych pod kątem zgodności z różnymi platformami. Aplikacje na Androida mogą odczytywać te same dane jako tablicę bajtów bez problemów ze zgodnością z różnymi platformami.

Wybierając format danych zapisanych gier, unikaj formatów specyficznych dla platformy. Zdecydowanie zalecamy używanie formatu danych, takiego jak XML lub JSON, który jest dobrze obsługiwany przez biblioteki na różnych platformach.

Włączanie usługi zapisanych gier

Zanim zaczniesz korzystać z usługi Zapisane gry, musisz najpierw włączyć do niej dostęp. Aby to zrobić, podczas tworzenia usługi wywołaj EnableSnapshots() za pomocą gpg::GameServices::Builder. Podczas następnego zdarzenia autoryzacji zostaną włączone dodatkowe zakresy autoryzacji wymagane przez zapisane gry.

Wyświetlanie zapisanych gier

W grze możesz udostępnić opcję, którą gracze mogą uruchomić, aby zapisać lub przywrócić zapisane gry. Gdy gracze wybiorą tę opcję, gra powinna wyświetlić ekran z istniejącymi miejscami zapisu i umożliwić zapisanie lub wczytanie stanu gry w jednym z nich albo utworzenie nowego zapisu. Aby to zrobić, wykonaj te czynności:

  SnapshotManager::ShowSelectUIOperation(...)

Interfejs wyboru zapisanych gier umożliwia graczom tworzenie nowych zapisanych gier, wyświetlanie szczegółów istniejących zapisanych gier i wczytywanie poprzednich zapisanych gier.

  SnapshotManager::SnapshotSelectUIResponse response;
  if (IsSuccess(response.status)) {
  if (response.data.Valid()) {
    LogI("Description: %s", response.data.Description().c_str());
    LogI("FileName %s", response.data.FileName().c_str());
    //Opening the snapshot data
    
  } else {
    LogI("Creating new snapshot");
    
  }
} else {
  LogI("ShowSelectUIOperation returns an error %d", response.status);
}

Poniższy przykład pokazuje, jak wyświetlić domyślny interfejs użytkownika zapisanych gier i obsłużyć wybór gracza:

  service_->Snapshots().ShowSelectUIOperation(
  ALLOW_CREATE_SNAPSHOT,
  ALLOW_DELETE_SNAPSHOT,
  MAX_SNAPSHOTS,
  SNAPSHOT_UI_TITLE,
  [this](gpg::SnapshotManager::SnapshotSelectUIResponse const & response) {
  
      }

Jeśli w przykładzie powyżej ALLOW_CREATE_SNAPSHOT to true, a MAX_SNAPSHOTS jest większe niż rzeczywista liczba zrzutów, które użytkownik utworzył do tej pory, domyślny interfejs zrzutów udostępnia graczom przycisk do utworzenia nowej gry zapisanej zamiast wyboru istniejącej. (Gdy przycisk jest wyświetlany, znajduje się u dołu interfejsu). Gdy gracz kliknie ten przycisk, odpowiedź SnapshotSelectUIResponse jest prawidłowa, ale nie zawiera danych.

Otwieranie i odczytywanie zapisanych gier

Aby uzyskać dostęp do zapisanej gry i odczytać lub zmodyfikować jej zawartość, najpierw otwórz obiekt SnapshotMetadata reprezentujący tę zapisaną grę. Następnie wywołaj metodę SnapshotManager::Read*().

Poniższy przykład pokazuje, jak otworzyć zapisaną grę:

  LogI("Opening file");
  service_->Snapshots()
  .Open(current_snapshot_.FileName(),
               gpg::SnapshotConflictPolicy::BASE_WINS,
        [this](gpg::SnapshotManager::OpenResponse const & response) {
           LogI("Reading file");
           gpg::SnapshotManager::ReadResponse responseRead =
           service_->Snapshots().ReadBlocking(response.data);
          
        }

Wykrywanie i rozwiązywanie konfliktów danych

Gdy otworzysz obiekt SnapshotMetadata, usługa Zapisane gry sprawdzi, czy istnieje konfliktujący zapis gry. Konflikty danych mogą wystąpić, gdy zapisana gra przechowywana na urządzeniu lokalnym gracza jest niezsynchronizowana z wersją zdalną przechowywaną na serwerach Google.

Zasady dotyczące konfliktów, które określasz podczas otwierania zapisanej gry, informują usługę Zapisane gry, jak automatycznie rozwiązywać konflikty danych. Zasada może mieć jedną z tych wartości:

Zasady dotyczące konfliktów Opis
SnapshotConflictPolicy::MANUAL Wskazuje, że usługa Zapisane gry nie powinna podejmować żadnych działań związanych z rozwiązywaniem problemów. Zamiast tego gra wykona niestandardowe scalanie.
SnapshotConflictPolicy::LONGEST_PLAYTIME Wskazuje, że usługa Zapisane gry powinna wybrać zapisaną grę z najdłuższym czasem gry.
SnapshotConflictPolicy::BASE_WINS Wskazuje, że usługa Zapisane gry powinna wybrać podstawowy zapisany stan gry.
SnapshotConflictPolicy::REMOTE_WINS Wskazuje, że usługa Zapisane gry powinna wybrać zdany zapis gry. Wersja zdalna to wersja zapisanej gry wykryta na jednym z urządzeń gracza, która ma nowszy sygnaturę czasową niż wersja podstawowa.

Jeśli określisz zasadę konfliktu inną niż GPGSnapshotConflictPolicyManual, usługa Zapisane gry scali zapisaną grę i zwróci zaktualizowaną wersję za pomocą wartości SnapshotManager::OpenResponse. Gra może otworzyć zapisaną grę, zapisać w niej dane, a następnie wywołać metodę SnapshotManager::Commit(...) , aby zapisać grę na serwerach Google.

Przeprowadzanie niestandardowego scalania

Jeśli jako zasadę rozwiązywania konfliktów podano SnapshotConflictPolicy::MANUAL, gra musi rozwiązać każdy wykryty konflikt danych, zanim wykona dalsze operacje odczytu lub zapisu w zapisanej grze.

W takim przypadku, gdy zostanie wykryty konflikt danych, usługa zwraca te parametry za pomocą SnapshotManager::OpenResponse:

  • conflict_id, aby jednoznacznie zidentyfikować ten konflikt (użyjesz tej wartości podczas zatwierdzania ostatecznej wersji zapisanego stanu gry);
  • sprzeczna wersja podstawowa zapisu gry;
  • Sprzeczna zdalna wersja zapisu gry.

Gra musi zdecydować, jakie dane ma zapisać, a następnie wywołać metodę SnapshotManager::ResolveConflictBlocking(), aby przesłać/rozwiązać ostateczną wersję na serwerach Google.

    //Resolve conflict
    gpg::SnapshotManager::OpenResponse resolveResponse =
        manager.ResolveConflictBlocking(openResponse.conflict_base, metadata_change,
                                  openResponse.conflict_id);

Zapisywanie gier

Aby zapisać grę, najpierw otwórz obiekt SnapshotMetadata reprezentujący zapisany stan gry, rozwiąż wykryte konflikty danych, a następnie wywołaj metodę SnapshotManager::Commit(), aby zatwierdzić zmiany w zapisanej grze.

Poniższy przykład pokazuje, jak utworzyć zmianę i zatwierdzić zapisaną grę.

  1. Najpierw otwórz migawkę, którą chcesz edytować, i upewnij się, że wszystkie konflikty zostały rozwiązane przez wybranie bazy.

    service_->Snapshots().Open(
          file_name,
          gpg::SnapshotConflictPolicy::BASE_WINS,
          [this](gpg::SnapshotManager::OpenResponse const &response) {
            if (IsSuccess(response.status)) {
              // metadata : gpg::SnapshotMetadata
              metadata = response.data;
            } else {
              // Handle snapshot open error here
            }
          });
    
  2. Następnie utwórz zmianę zapisu gry, która zawiera dane obrazu używane na potrzeby obrazu okładki:

    gpg::SnapshotMetadataChange::Builder builder;
    gpg::SnapshotMetadataChange metadata_change =
        builder.SetDescription("CollectAllTheStar savedata")
                 .SetCoverImageFromPngData(pngData).Create();
    
  3. Na koniec zatwierdź zapisane zmiany w grze.

    gpg::SnapshotManager::CommitResponse commitResponse =
        service_->Snapshots().CommitBlocking(metadata, metadata_change, SetupSnapshotData());
    

    Parametr data zawiera wszystkie przechowywane dane zapisu stanu gry. Zmiana zawiera też dodatkowe metadane zapisu stanu gry, takie jak czas gry i opis zapisu stanu gry.

Jeśli operacja zatwierdzenia się powiedzie, gracze zobaczą zapisaną grę w interfejsie wyboru zapisanych gier.