Dodawanie zapisanych gier do gry

Ten przewodnik pokazuje, jak zapisać i wczytać dane o postępach gracza za pomocą usługi Zapisane gry w aplikacji C++. Możesz korzystać z tej usługi, aby automatycznie wczytywać i zapisywać postępy w grze w dowolnym momencie rozgrywki. Dzięki tej usłudze gracze mogą też aktywować interfejs użytkownika, aby zaktualizować lub przywrócić istniejącą grę, a także utworzyć nową.

Zanim zaczniesz

Warto zapoznać się z koncepcjami dotyczącymi zapisanych gier.

Zanim zaczniesz kodować za pomocą interfejsu Saved Games API:

Formaty danych i zgodność z wieloma platformami

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

Unikaj wyboru formatów danych charakterystycznych dla platformy podczas wyboru formatu danych dla zapisanych gier. Zdecydowanie zalecamy korzystanie z formatu danych, takiego jak XML lub JSON, który obsługuje wiele bibliotek na wielu platformach.

Włączanie usługi Zapisane gry

Aby korzystać z usługi Zapisane gry, musisz najpierw włączyć w niej dostęp. Aby to zrobić, wywołaj funkcję EnableSnapshots() podczas tworzenia usługi za pomocą gpg::GameServices::Builder. Spowoduje to włączenie dodatkowych zakresów uwierzytelniania wymaganych przez zapisane gry podczas następnego zdarzenia uwierzytelniania.

Wyświetlam zapisane gry

Możesz wybrać opcję, dzięki której gracze będą mogli zapisywać lub przywracać zapisane gry. Gdy użytkownik wybierze tę opcję, gra powinna wyświetlić ekran z dowolnym zapisanym miejscem i umożliwić graczowi zapisanie gry lub wczytanie go z jednego z tych boksów albo utworzenie nowej zapisanej gry. Aby to zrobić:

  SnapshotManager::ShowSelectUIOperation(...)

Interfejs wyboru usługi Zapisane gry umożliwia graczom tworzenie nowej zapisanej gry, wyświetlanie informacji o zapisanych grach oraz wczytywanie wcześniej 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 zapisanych gier i obsługiwać wybór interfejsu gracza:

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

Jeśli w powyższym przykładzie ALLOW_CREATE_SNAPSHOT ma wartość true, a MAX_SNAPSHOTS jest większa niż rzeczywista liczba zrzutów utworzonych przez użytkownika, domyślny interfejs Snapshot daje graczom przycisk do utworzenia nowej gry, zamiast wyboru istniejącej. Gdy przycisk jest widoczny, znajduje się na dole interfejsu. Gdy odtwarzacz kliknie ten przycisk, odpowiedź SnapshotSelectUIResponse jest prawidłowa, ale nie ma żadnych danych.

Otwieranie i odczytywanie zapisanych gier

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

Ten 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 otwierasz obiekt SnapshotMetadata, usługa Zapisane gry wykrywa, czy istnieje zapisana konflikt gry. Konflikty danych mogą wystąpić, gdy zapisana gra zapisana na urządzeniu lokalnym użytkownika nie jest zsynchronizowana z wersją zdalną zapisaną na serwerach Google.

Zasady konfliktu, które określisz podczas otwierania zapisanej gry, informują usługę gier o tym, jak automatycznie rozwiązać konflikt danych. Oto możliwe zasady:

Zasady dotyczące konfliktów Opis
SnapshotConflictPolicy::MANUAL Wskazuje, że usługa Zapisane gry nie powinna podejmować żadnych działań w celu rozwiązania problemu. Zamiast tego przeprowadzisz niestandardowe scalanie gry.
SnapshotConflictPolicy::LONGEST_PLAYTIME Wskazuje, że usługa Zapisane gry powinna wybrać zapisaną grę z największą wartością czasu gry.
SnapshotConflictPolicy::BASE_WINS Wskazuje, że usługa Zapisane gry powinna wybrać podstawową zapisaną grę.
SnapshotConflictPolicy::REMOTE_WINS Wskazuje, że usługa Zapisane gry powinna wybrać zapisaną zdalnie grę. Wersja zdalna to wersja zapisanej gry, która jest wykrywana na jednym z urządzeń odtwarzacza i ma nowszą sygnaturę czasową niż wersja podstawowa.

Jeśli w przypadku konfliktu określono inne zasady 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ę, napisać do niej tekst, a potem wywołać metodę SnapshotManager::Commit(...), by zapisać zapisaną grę na serwerach Google.

Niestandardowe scalanie

Jeśli jako zasadę konfliktu masz ustawione SnapshotConflictPolicy::MANUAL, Twoja gra musi rozwiązać wszelkie konflikty danych wykryte przed wykonaniem dalszych operacji odczytu lub zapisu w zapisanej grze.

W tym przypadku, gdy zostanie wykryty konflikt danych, usługa zwraca następujące parametry: SnapshotManager::OpenResponse:

  • conflict_id, aby jednoznacznie identyfikować konflikt (wartość ta będzie używana podczas zatwierdzania ostatecznej wersji zapisanej gry);
  • sprzeczna podstawowa wersja zapisanej gry,
  • Zdalna wersja zapisanej gry.

Gra musi zdecydować, jakie dane mają być zapisywane, a następnie wywołać metodę SnapshotManager::ResolveConflictBlocking(), by zatwierdzić/ukończyć ostateczną wersję na serwerach Google.

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

Zapisywanie zapisanych gier

Aby napisać zapisaną grę, najpierw otwórz obiekt SnapshotMetadata reprezentujący zapisaną grę, rozwiąż wszystkie 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 zrzut, który chcesz edytować, i sprawdź, czy wszystkie konflikty zostały rozwiązane, wybierając podstawę.

    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 zapisaną zmianę w grze, która zawiera dane obrazu użytego na okładce:

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

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

    Parametr danych zawiera wszystkie przechowywane dane gier, które przechowujesz. Ta zmiana obejmuje też dodatkowe metadane gry, takie jak czas jej gry, i jej opis.

Jeśli operacja się powiodła, gracze mogą zobaczyć zapisaną grę w interfejsie wyboru zapisanych gier.