Добавление сохраненных игр в вашу игру

В этом руководстве показано, как сохранять и загружать данные о ходе игры игрока с помощью службы «Сохраненные игры» в приложении C++. Вы можете использовать этот сервис для автоматической загрузки и сохранения игрового прогресса игрока в любой момент игры. Этот сервис также может позволить игрокам запускать пользовательский интерфейс для обновления или восстановления существующей сохраненной игры или создания новой.

Прежде чем вы начнете

Если вы еще этого не сделали, возможно, вам будет полезно просмотреть концепции игры «Сохраненные игры» .

Прежде чем начать писать код с помощью API сохраненных игр:

Форматы данных и кроссплатформенная совместимость

Данные сохраненных игр, которые вы сохраняете на серверах Google, должны быть в формате std::vector<uint8_t> . Служба сохраненных игр позаботится о кодировании ваших данных для обеспечения кросс-платформенной совместимости; Приложения Android могут считывать те же данные в виде байтового массива без каких-либо проблем с кросс-платформенной совместимостью.

Избегайте использования форматов, специфичных для конкретной платформы, при выборе формата данных для сохраненных игр. Мы настоятельно рекомендуем вам использовать формат данных, например XML или JSON, который имеет надежную библиотечную поддержку на нескольких платформах.

Включение службы сохраненных игр

Прежде чем вы сможете использовать службу «Сохраненные игры», необходимо сначала разрешить к ней доступ. Для этого вызовите EnableSnapshots() при создании службы с помощью gpg::GameServices::Builder . Это активирует дополнительные области аутентификации, необходимые для сохраненных игр, при следующем событии аутентификации.

Отображение сохраненных игр

В своей игре вы можете предоставить игрокам возможность сохранять или восстанавливать сохраненные игры. Когда игроки выбирают эту опцию, ваша игра должна открыть экран, на котором отображаются существующие слоты для сохранения, и позволить игрокам либо сохранить игру, либо загрузить ее из одной из этих ячеек, либо создать новую сохраненную игру. Для этого используйте следующий метод:

  SnapshotManager::ShowSelectUIOperation(...)

Пользовательский интерфейс выбора сохраненных игр позволяет игрокам создавать новые сохраненные игры, просматривать сведения о существующих сохраненных играх и загружать предыдущие сохраненные игры.

  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);
}

В следующем примере показано, как вызвать пользовательский интерфейс сохраненных игр по умолчанию и обработать выбор пользовательского интерфейса игрока:

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

Если в приведенном выше примере ALLOW_CREATE_SNAPSHOT имеет true , а MAX_SNAPSHOTS больше, чем фактическое количество снимков, созданных пользователем в данный момент, пользовательский интерфейс снимков по умолчанию предоставляет игрокам кнопку для создания нового сохранения игры, а не выбора существующего. (Когда кнопка отображается, она находится в нижней части пользовательского интерфейса.) Когда игрок нажимает на эту кнопку, ответ SnapshotSelectUIResponse действителен, но не содержит данных.

Открытие и чтение сохраненных игр

Чтобы получить доступ к сохраненной игре и прочитать или изменить ее содержимое, сначала откройте объект SnapshotMetadata представляющий эту сохраненную игру. Затем вызовите метод SnapshotManager::Read*() .

В следующем примере показано, как открыть сохраненную игру:

  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);
          …
        }

Обнаружение и разрешение конфликтов данных

Когда вы открываете объект SnapshotMetadata , служба сохраненных игр определяет, существует ли конфликтующая сохраненная игра. Конфликты данных могут возникнуть, если сохраненная игра, хранящаяся на локальном устройстве игрока, не синхронизирована с удаленной версией, хранящейся на серверах Google.

Политика конфликтов, которую вы указываете при открытии сохраненной игры, сообщает службе сохраненных игр, как автоматически разрешать конфликт данных. Политика может быть одной из следующих:

Конфликтная политика Описание
SnapshotConflictPolicy::MANUAL Указывает, что служба сохраненных игр не должна выполнять никаких действий по разрешению проблемы. Вместо этого ваша игра выполнит пользовательское слияние .
SnapshotConflictPolicy::LONGEST_PLAYTIME Указывает, что служба сохраненных игр должна выбрать сохраненную игру с наибольшим значением времени игры.
SnapshotConflictPolicy::BASE_WINS Указывает, что служба сохраненных игр должна выбрать базовую сохраненную игру.
SnapshotConflictPolicy::REMOTE_WINS Указывает, что служба сохраненных игр должна выбрать удаленную сохраненную игру. Удаленная версия — это версия сохраненной игры, которая обнаруживается на одном из устройств игрока и имеет более позднюю временную метку, чем базовая версия.

Если вы указали политику конфликтов, отличную от GPGSnapshotConflictPolicyManual , служба сохраненных игр объединит сохраненную игру и вернет обновленную версию через результирующее значение SnapshotManager::OpenResponse . Ваша игра может открыть сохраненную игру, записать в нее данные, а затем вызвать метод SnapshotManager::Commit(...) для передачи сохраненной игры на серверы Google.

Выполнение пользовательского слияния

Если вы указали SnapshotConflictPolicy::MANUAL в качестве политики конфликтов, ваша игра должна разрешить любой обнаруженный конфликт данных, прежде чем выполнять дальнейшие операции чтения или записи в сохраненной игре.

В этом случае при обнаружении конфликта данных сервис возвращает через SnapshotManager::OpenResponse следующие параметры:

  • conflict_id для уникальной идентификации этого конфликта (вы будете использовать это значение при фиксации финальной версии сохраненной игры);
  • Противоречивая базовая версия сохраненной игры; и,
  • Конфликтующая удаленная версия сохраненной игры.

Ваша игра должна решить, какие данные сохранять, а затем вызвать метод SnapshotManager::ResolveConflictBlocking() чтобы передать/разрешить окончательную версию на серверах Google.

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

Написание сохраненных игр

Чтобы записать сохраненную игру, сначала откройте объект SnapshotMetadata , представляющий эту сохраненную игру, устраните все обнаруженные конфликты данных, а затем вызовите метод SnapshotManager::Commit() чтобы зафиксировать изменения сохраненной игры.

В следующем примере показано, как можно внести изменения и зафиксировать сохраненную игру.

  1. Сначала откройте снимок, который мы хотим отредактировать, и убедитесь, что все конфликты разрешены путем выбора базы.

    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. Затем создайте сохраненное изменение игры, включающее данные изображения, используемые для обложки:

    gpg::SnapshotMetadataChange::Builder builder;
    gpg::SnapshotMetadataChange metadata_change =
        builder.SetDescription("CollectAllTheStar savedata")
                 .SetCoverImageFromPngData(pngData).Create();
    
  3. Наконец, зафиксируйте сохраненные изменения игры.

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

    Параметр data содержит все данные сохранения игры, которые вы храните. Изменение также содержит дополнительные метаданные сохраненной игры, такие как сыгранное время и описание сохраненной игры.

Если операция фиксации завершилась успешно, игроки смогут увидеть сохраненную игру в пользовательском интерфейсе выбора сохраненных игр.