Cómo agregar juegos guardados a tu juego

En esta guía, se muestra cómo guardar y cargar los datos de progreso del juego de un jugador mediante el servicio de Juegos guardados en una aplicación de C++. Puedes usar este servicio para cargar y guardar automáticamente el progreso del juego en cualquier momento durante el juego. Este servicio también puede permitir a los jugadores activar una interfaz de usuario para actualizar o restablecer un juego guardado existente, o crear uno nuevo.

Antes de comenzar

Si aún no lo hiciste, puede resultarte útil revisar los conceptos de juegos guardados.

Antes de comenzar a programar con la API de Saved Games:

Formatos de datos y compatibilidad multiplataforma

Los datos de Juegos guardados que guardas en los servidores de Google deben estar en formato std::vector<uint8_t>. El servicio de Juegos guardados se encarga de codificar los datos a fin de mejorar la compatibilidad entre plataformas. Las aplicaciones para Android pueden leer estos mismos datos como un arreglo de bytes sin problemas de compatibilidad entre plataformas.

Evita usar formatos específicos de la plataforma cuando elijas un formato de datos para los datos de los juegos guardados. Te recomendamos que uses un formato de datos, como XML o JSON, que sea compatible con bibliotecas sólidas en varias plataformas.

Cómo habilitar el servicio de juegos guardados

Antes de poder usar el servicio de Juegos guardados, debes habilitar el acceso a él. Para ello, llama a EnableSnapshots() cuando crees el servicio con gpg::GameServices::Builder. Esto habilitará los permisos de autenticación adicionales que requieren los Juegos guardados en el próximo evento.

Se muestran los juegos guardados

En tu juego, puedes proporcionar una opción que los jugadores puedan activar para guardar o restablecer los juegos guardados. Cuando los jugadores seleccionan esta opción, el juego debe abrir una pantalla que muestra las ranuras de guardado existentes y permitir que los jugadores guarden o carguen una de estas ranuras, o bien que creen un juego guardado nuevo. Usa el siguiente método para hacerlo:

  SnapshotManager::ShowSelectUIOperation(...)

La IU de selección de Juegos guardados permite a los jugadores crear un juego guardado nuevo, ver los detalles de los juegos guardados existentes y cargar los juegos guardados anteriores.

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

En el siguiente ejemplo, se muestra cómo abrir la IU predeterminada de los juegos guardados y controlar la selección de la IU del jugador:

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

Si, en el ejemplo anterior, ALLOW_CREATE_SNAPSHOT es true y MAX_SNAPSHOTS es mayor que la cantidad real de instantáneas que creó el usuario, la IU de Snapshot predeterminada les brinda a los jugadores un botón para crear un juego de guardado nuevo en lugar de seleccionar uno existente. (Cuando se muestra, el botón está en la parte inferior de la IU). Cuando un jugador hace clic en este botón, la respuesta SnapshotSelectUIResponse es válida, pero no tiene datos.

Abrir y leer los juegos guardados

Para acceder a un juego guardado y leer o modificar su contenido, primero abre el objeto SnapshotMetadata que representa ese juego guardado. A continuación, llama al método SnapshotManager::Read*().

En el siguiente ejemplo, se muestra cómo abrir un juego guardado:

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

Detección y resolución de conflictos de datos

Cuando abres un objeto SnapshotMetadata, el servicio de Juegos guardados detecta si existe un juego guardado en conflicto. Los conflictos de datos pueden ocurrir cuando el juego guardado que se almacena en el dispositivo local de un jugador no está sincronizado con la versión remota almacenada en los servidores de Google.

La política de conflicto que especificas cuando abres un juego guardado le indica al servicio de juegos guardados cómo resolver automáticamente un conflicto de datos. La política puede ser una de las siguientes:

Política de conflicto Descripción
SnapshotConflictPolicy::MANUAL Indica que el servicio de Juegos guardados no debe realizar ninguna acción de resolución. En cambio, el juego realizará una combinación personalizada.
SnapshotConflictPolicy::LONGEST_PLAYTIME Indica que el servicio de juegos guardados debe elegir el juego guardado con el mayor valor de tiempo de juego.
SnapshotConflictPolicy::BASE_WINS Indica que el servicio de Juegos guardados debe elegir el juego guardado base.
SnapshotConflictPolicy::REMOTE_WINS Indica que el servicio de Juegos guardados debe elegir el juego remoto guardado. La versión remota es una versión del juego guardado que se detecta en uno de los dispositivos del jugador y tiene una marca de tiempo más reciente que la versión base.

Si especificaste una política de conflicto distinta de GPGSnapshotConflictPolicyManual, el servicio de Juegos guardados combinará el juego guardado y mostrará la versión actualizada a través del valor SnapshotManager::OpenResponse resultante. El juego puede abrir el juego guardado, escribir en él y llamar al método SnapshotManager::Commit(...) para confirmar el juego guardado en los servidores de Google.

Cómo realizar una combinación personalizada

Si especificaste SnapshotConflictPolicy::MANUAL como política de conflicto, tu juego debe resolver cualquier conflicto de datos que se detecte antes de realizar más operaciones de lectura o escritura en el juego guardado.

En este caso, cuando se detecta un conflicto de datos, el servicio muestra los siguientes parámetros a través de SnapshotManager::OpenResponse:

  • Un conflict_id para identificar de forma exclusiva este conflicto (usarás este valor cuando confirmes la versión final del juego guardado)
  • La versión base en conflicto del juego guardado
  • La versión remota en conflicto del juego guardado.

Tu juego debe decidir qué datos guardar y, luego, llamar al método SnapshotManager::ResolveConflictBlocking() para confirmar o resolver la versión final en los servidores de Google.

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

Cómo escribir juegos guardados

Para escribir un juego guardado, primero abre el objeto SnapshotMetadata que representa ese juego, resuelve cualquier conflicto de datos detectado y, luego, llama al método SnapshotManager::Commit() para confirmar los cambios.

En el siguiente ejemplo, se muestra cómo puedes crear un cambio y confirmar un juego guardado.

  1. Primero, abre la instantánea que queremos editar y asegúrate de resolver todos los conflictos.

    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. A continuación, crea un cambio de juego guardado que incluya los datos de imagen usados para la imagen de portada:

    gpg::SnapshotMetadataChange::Builder builder;
    gpg::SnapshotMetadataChange metadata_change =
        builder.SetDescription("CollectAllTheStar savedata")
                 .SetCoverImageFromPngData(pngData).Create();
    
  3. Por último, confirma los cambios guardados del juego.

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

    El parámetro de datos contiene todos los datos guardados del juego que almacenas. El cambio también contiene metadatos adicionales guardados sobre el juego, como el tiempo de juego jugado y una descripción del juego guardado.

Si la operación de confirmación se completó correctamente, los jugadores podrán ver el juego guardado en la IU de selección de Juegos guardados.