保存済みゲームをゲームに追加する

このガイドでは、C++ アプリで保存済みゲームサービスを使用してプレーヤーのゲームの進行状況データを保存し、読み込める方法について説明します。このサービスを使用すると、ゲームプレイ中の任意の場所でプレーヤーのゲームの進行状況を自動的に読み込み、保存できます。このサービスでは、プレーヤーが既存のセーブゲームを更新または復元するためのユーザー インターフェースをトリガーすることや、新しいセーブゲームを作成することもできます。

始める前に

保存済みゲームのコンセプトをまだ確認されていない場合は、確認することをおすすめします。

Saved Games API を使用してコーディングを開始する前に:

データ形式とクロス プラットフォームの互換性

Google のサーバーに保存する保存済みゲームデータは、std::vector<uint8_t> 形式である必要があります。保存済みゲームサービスは、クロス プラットフォームの互換性を確保するために、データのエンコードを行います。Android アプリは、プラットフォームをまたいだ互換性の問題なしに、この同じデータをバイト配列として読み取ることができます。

保存済みゲームデータのデータ形式を選択する際は、プラットフォーム固有の形式を使用しないでください。複数のプラットフォームで強力なライブラリ サポートのある XML や JSON などのデータ形式を使用することを強くおすすめします。

保存済みゲームサービスを有効にする

保存済みゲームサービスを使用するには、まず、そのゲームへのアクセスを有効にする必要があります。これを行うには、gpg::GameServices::Builder を使用してサービスを作成するときに EnableSnapshots() を呼び出します。これにより、次の認証イベントで、保存済みゲームに必要な追加の認証スコープが有効になります。

保存済みゲームの表示

ゲームでは、保存済みゲームの保存または復元をプレーヤーがトリガーできるオプションを指定できます。プレーヤーがこのオプションを選択すると、ゲームは既存のセーブスロットを表示する画面を表示し、プレーヤーがスロットの 1 つに保存または読み込みを行えるようにするか、新しい保存済みゲームを作成できるようにする必要があります。これを行うには、次のメソッドを使用します。

  SnapshotManager::ShowSelectUIOperation(...)

保存済みゲーム選択 UI により、プレーヤーは、新しい保存済みゲームの作成、既存の保存済みゲームの詳細表示、以前の保存済みゲームの読み込みを行えます。

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

次の例は、デフォルトの保存済みゲーム UI を表示し、プレーヤーの UI 選択を処理する方法を示しています。

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

上記の例で、ALLOW_CREATE_SNAPSHOTtrue で、MAX_SNAPSHOTS がユーザーが現在作成したスナップショットの数よりも大きい場合、デフォルトの Snapshot UI は、既存のスナップショットを選択する代わりに、新しいセーブゲームを作成するボタンをプレーヤーに提供します。(ボタンが表示された場合、ボタンは UI の下部にあります)。プレーヤーがこのボタンをクリックすると、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 のサーバーに commit できます。

カスタムマージを実行する

競合ポリシーとして SnapshotConflictPolicy::MANUAL を指定した場合、保存済みゲームに対して読み取りまたは書き込みオペレーションを実行する前に、検出されたデータの競合をゲームで解決する必要があります。

この場合、データの競合が検出されると、サービスは SnapshotManager::OpenResponse を介して次のパラメータを返します。

  • この競合を一意に識別する conflict_id(保存済みゲームの最終バージョンを commit するときにこの値を使用します)。
  • 保存済みゲームの競合する基本バージョン
  • 保存済みゲームの競合するリモート バージョン。

ゲームは保存するデータを決定し、SnapshotManager::ResolveConflictBlocking() メソッドを呼び出して、最終バージョンを Google のサーバーに commit / 解決する必要があります。

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

保存済みゲームの作成

保存済みゲームを作成するには、まずその保存済みゲームを表す SnapshotMetadata オブジェクトを開き、検出されたデータ競合を解決してから、SnapshotManager::Commit() メソッドを呼び出して保存済みゲームの変更を確定します。

次の例は、変更を作成して、保存済みゲームを 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 パラメータには、保存するすべてのセーブゲーム データが含まれます。この変更には、プレイ時間や保存済みゲームの説明など、保存済みゲームのメタデータも含まれます。

commit オペレーションが正常に完了すると、保存済みゲーム選択 UI に保存済みゲームが表示されます。