Ajouter des jeux enregistrés à votre jeu

Ce guide vous explique comment enregistrer et charger les données de progression d'un jeu à l'aide du service Jeux enregistrés dans une application C++. Vous pouvez utiliser ce service pour charger et enregistrer automatiquement la progression dans le jeu à tout moment pendant le jeu. Ce service peut également permettre aux joueurs de déclencher une interface utilisateur pour mettre à jour ou restaurer un jeu existant, ou d'en créer un.

Avant de commencer

Si ce n'est pas déjà fait, vous pouvez consulter les concepts de jeux enregistrés.

Avant de commencer à coder à l'aide de l'API Saved Games:

Formats de données et compatibilité multiplate-forme

Les données de jeux enregistrées que vous enregistrez sur les serveurs de Google doivent être au format std::vector<uint8_t>. Le service Jeux enregistrés se charge d'encoder vos données pour la compatibilité multiplate-forme. Les applications Android peuvent lire ces mêmes données sous la forme d'un tableau d'octets sans problème de compatibilité multiplate-forme.

Évitez d'utiliser des formats spécifiques à la plate-forme lorsque vous choisissez un format pour vos données de jeux enregistrés. Nous vous encourageons vivement à utiliser un format de données, tel que XML ou JSON, qui est fortement compatible avec les bibliothèques sur plusieurs plates-formes.

Activer le service Jeux enregistrés

Avant de pouvoir utiliser le service Jeux enregistrés, vous devez d'abord autoriser l'accès à celui-ci. Pour ce faire, appelez EnableSnapshots() lorsque vous créez le service avec gpg::GameServices::Builder. Cela activera les champs d'application d'authentification supplémentaires requis par les jeux enregistrés lors du prochain événement d'authentification.

Affichage des jeux enregistrés

Dans votre jeu, vous pouvez fournir une option que les joueurs peuvent déclencher pour enregistrer ou restaurer des jeux enregistrés. Lorsque les joueurs sélectionnent cette option, le jeu doit afficher un écran qui affiche les emplacements de sauvegarde existants, et leur permet d'enregistrer ou de charger l'un de ces emplacements, ou de créer un jeu enregistré. Pour ce faire, utilisez la méthode suivante:

  SnapshotManager::ShowSelectUIOperation(...)

L'interface utilisateur de sélection de jeux enregistrés permet aux joueurs de créer un jeu enregistré, de consulter les détails des jeux enregistrés existants et de charger les parties précédentes.

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

L'exemple suivant montre comment afficher l'interface utilisateur de jeux enregistrés par défaut et gérer la sélection de l'interface utilisateur du joueur:

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

Si, dans l'exemple ci-dessus, ALLOW_CREATE_SNAPSHOT est true et que MAX_SNAPSHOTS est supérieur au nombre réel d'instantanés actuellement créés par l'utilisateur, l'interface utilisateur par défaut de l'instantané fournit aux joueurs un bouton permettant de créer un jeu d'enregistrement, plutôt que de sélectionner un jeu existant. Lorsqu'il s'affiche, le bouton se trouve en bas de l'interface utilisateur. Lorsqu'un joueur clique sur ce bouton, la réponse SnapshotSelectUIResponse est valide, mais ne contient aucune donnée.

Ouvrir et lire les jeux enregistrés

Pour accéder à un jeu enregistré, et lire ou modifier son contenu, ouvrez d'abord l'objet SnapshotMetadata représentant ce jeu enregistré. Appelez ensuite la méthode SnapshotManager::Read*().

L'exemple suivant montre comment ouvrir un jeu enregistré:

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

Détecter et résoudre les conflits de données

Lorsque vous ouvrez un objet SnapshotMetadata, le service de jeux enregistrés détecte si un jeu enregistré en conflit existe. Des conflits de données peuvent se produire lorsque le jeu enregistré stocké sur l'appareil local d'un joueur n'est pas synchronisé avec la version distante stockée sur les serveurs de Google.

La règle de conflit que vous spécifiez lors de l'ouverture d'un jeu enregistré indique au service de jeux enregistrés comment résoudre automatiquement un conflit de données. La règle peut être l'une des suivantes:

Politique de conflit Description
SnapshotConflictPolicy::MANUAL Indique que le service Jeux enregistrés ne doit effectuer aucune action de résolution. Au lieu de cela, votre jeu effectue une fusion personnalisée.
SnapshotConflictPolicy::LONGEST_PLAYTIME Indique que le service Jeux enregistrés doit sélectionner celui dont la durée de jeu est la plus élevée.
SnapshotConflictPolicy::BASE_WINS Indique que le service Jeux enregistrés doit sélectionner le jeu enregistré de base.
SnapshotConflictPolicy::REMOTE_WINS Indique que le service Jeux enregistrés doit sélectionner le jeu enregistré à distance. La version distante est une version du jeu enregistré qui est détectée sur l'un des appareils du joueur et dont l'horodatage est plus récent que celui de la version de base.

Si vous avez spécifié une règle de conflit autre que GPGSnapshotConflictPolicyManual, le service Jeux enregistrés fusionne le jeu enregistré et renvoie la version mise à jour via la valeur SnapshotManager::OpenResponse résultante. Votre jeu peut ouvrir le jeu enregistré, y écrire, puis appeler la méthode SnapshotManager::Commit(...) pour valider le jeu enregistré sur les serveurs de Google.

Effectuer une fusion personnalisée

Si vous avez spécifié SnapshotConflictPolicy::MANUAL comme stratégie de conflit, votre jeu doit résoudre tout conflit de données détecté avant d'effectuer d'autres opérations de lecture ou d'écriture sur le jeu enregistré.

Dans ce cas, lorsqu'un conflit de données est détecté, le service renvoie les paramètres suivants via SnapshotManager::OpenResponse:

  • Un conflict_id pour identifier de manière unique ce conflit (vous utiliserez cette valeur pour valider la version finale du jeu enregistré)
  • la version de base en conflit du jeu enregistré ;
  • Version à distance en conflit du jeu enregistré.

Votre jeu doit décider quelles données enregistrer, puis appeler la méthode SnapshotManager::ResolveConflictBlocking() pour valider/résoudre la version finale sur les serveurs de Google.

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

Écriture de jeux enregistrés

Pour écrire un jeu enregistré, ouvrez d'abord l'objet SnapshotMetadata représentant ce jeu enregistré, résolvez les éventuels conflits de données, puis appelez la méthode SnapshotManager::Commit() pour valider vos modifications de jeu enregistrées.

L'exemple suivant montre comment créer une modification et valider un jeu enregistré.

  1. Tout d'abord, ouvrez l'instantané que vous souhaitez modifier et assurez-vous que tous les conflits sont résolus en choisissant la base.

    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. Ensuite, créez une modification de jeu enregistrée qui inclut les données d'image utilisées pour l'image de couverture:

    gpg::SnapshotMetadataChange::Builder builder;
    gpg::SnapshotMetadataChange metadata_change =
        builder.SetDescription("CollectAllTheStar savedata")
                 .SetCoverImageFromPngData(pngData).Create();
    
  3. Enfin, validez les modifications de jeu enregistrées.

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

    Le paramètre de données contient toutes les données de sauvegarde que vous stockez. La modification contient également d'autres métadonnées de jeu enregistrées, telles que le temps de jeu et une description du jeu enregistré.

Si l'opération de validation aboutit, les joueurs peuvent voir le jeu enregistré dans l'interface utilisateur de la sélection de jeux enregistrés.