Ajouter des jeux enregistrés à votre jeu

Ce guide explique comment enregistrer et charger les données de progression d'un joueur à l'aide du service Jeux enregistrés dans une application C++. Vous pouvez utiliser ce service pour charger et enregistrer automatiquement la progression du joueur 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 une partie enregistrée existante, ou en créer une.

Avant de commencer

Si ce n'est pas déjà fait, n'hésitez pas à revoir les concepts de jeux de sauvegarde.

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

Formats de données et compatibilité multiplate-forme

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

Évitez d'utiliser des formats spécifiques à la plate-forme lorsque vous choisissez un format de données pour vos données Jeux enregistrés. Nous vous recommandons vivement d'utiliser un format de données, comme XML ou JSON, qui est compatible avec de nombreuses 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 activer l'accès à celui-ci. Pour ce faire, appelez EnableSnapshots() lorsque vous créez le service avec gpg::GameServices::Builder. Cela activera les portées d'autorisation supplémentaires requises par les jeux enregistrés lors du prochain événement d'autorisation.

Afficher les 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, votre jeu doit afficher un écran qui affiche les emplacements de sauvegarde existants et leur permettre d'enregistrer ou de charger à partir de l'un de ces emplacements, ou de créer un jeu enregistré. Pour ce faire, utilisez la méthode suivante:

  SnapshotManager::ShowSelectUIOperation(...)

L'UI de sélection des 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 de précédents jeux enregistrés.

  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'UI de jeux enregistrés par défaut et gérer la sélection de l'UI 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 que l'utilisateur a actuellement créés, l'UI par défaut de l'instantané fournit aux joueurs un bouton permettant de créer une nouvelle sauvegarde plutôt que de sélectionner une sauvegarde existante. (Lorsque le bouton s'affiche, il 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 des jeux enregistrés

Pour accéder à une partie enregistrée et lire ou modifier son contenu, ouvrez d'abord l'objet SnapshotMetadata qui la représente. Appelez ensuite la méthode SnapshotManager::Read*().

L'exemple suivant montre comment ouvrir une partie enregistrée:

  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 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 plus synchronisé avec la version distante stockée sur les serveurs de Google.

La stratégie de conflit que vous spécifiez lorsque vous ouvrez un jeu enregistré indique au service Jeux enregistrés comment résoudre automatiquement un conflit de données. La stratégie peut être l'une des suivantes:

Règlement sur les conflits Description
SnapshotConflictPolicy::MANUAL Indique que le service de jeux enregistrés ne doit effectuer aucune action de résolution. Votre jeu effectuera plutôt une fusion personnalisée.
SnapshotConflictPolicy::LONGEST_PLAYTIME Indique que le service Jeux enregistrés doit sélectionner le jeu enregistré avec la plus grande valeur de durée de jeu.
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é détectée sur l'un des appareils du joueur et dont le code temporel est plus récent que celui de la version de base.

Si vous avez spécifié une stratégie de conflit autre que GPGSnapshotConflictPolicyManual, le service de jeux enregistrés fusionnera le jeu enregistré et renverra la version mise à jour via la valeur SnapshotManager::OpenResponse générée. Votre jeu peut ouvrir la partie enregistrée, y écrire, puis appeler la méthode SnapshotManager::Commit(...) pour enregistrer la partie 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 la partie enregistrée.

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 lorsque vous validerez la version finale du jeu enregistré) ;
  • La version de base du jeu enregistré en conflit ;
  • Version distante en conflit de la partie enregistrée.

Votre jeu doit déterminer 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);

Écrire des jeux enregistrés

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

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 partie 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 apportées à la partie enregistrée.

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

    Le paramètre "data" contient toutes les données de sauvegarde que vous stockez. La modification contient également des métadonnées de jeu enregistrées supplémentaires, telles que la durée de jeu et une description du jeu enregistré.

Si l'opération de validation a réussi, les joueurs peuvent voir le jeu enregistré dans l'UI de sélection des jeux enregistrés.