2010-09-16 17 views
6

Estoy tratando de abrirme camino a través de la documentación de XNA MSDN para guardar y leer datos del juego, y no estoy teniendo mucha suerte.¿Cuál es un buen ejemplo de guardar datos de juegos en XNA 4.0?

En esencia, tengo una clase de administrador que realiza un seguimiento de varias instancias de clases base.

Quiero ser capaz de guardar el estado de toda la lista de objetos que el administrador está siguiendo y luego cargarlos la próxima vez que se cargue el juego. Básicamente, guardando el estado del mundo.

Respuesta

15

Si usa el XmlSerializer como se muestra en la ayuda de XNA 4.0, las clases base deben tener el atributo [XmlInclude (Type)] especificado para cada tipo concreto con el que se pueden serializar.

A continuación se muestra un ejemplo de cómo guardar datos de juegos en XNA 4.0. Presione F1 para guardar una vez que el juego se está ejecutando. Los datos se guardarán en una ubicación similar a C: \ Users \ {username} \ Documents \ SavedGames \ WindowsGame \ Game1StorageContainer \ Player1.

Cargar los datos nuevamente es un proceso muy similar.

Para que esto funcione en XBox agregue referencias a Microsoft.Xna.Framework.GamerServices & System.Xml.Serialization.

using System; 
using System.Collections.Generic; 
using System.Diagnostics; 
using System.IO; 
using System.Xml.Serialization; 
using Microsoft.Xna.Framework; 
using Microsoft.Xna.Framework.Graphics; 
using Microsoft.Xna.Framework.Input; 
using Microsoft.Xna.Framework.Storage; 
using Microsoft.Xna.Framework.GamerServices; 

namespace WindowsGame 
{ 
    [XmlInclude(typeof(Soldier)), XmlInclude(typeof(Grenade))] 
    public class BaseGameObject 
    { 
     public Vector3 Position { get; set; } 
    } 

    public class Soldier : BaseGameObject 
    { 
     public float Health { get; set; } 
    } 

    public class Grenade : BaseGameObject 
    { 
     public float TimeToDetonate { get; set; } 
    } 

    public struct SaveGameData 
    { 
     public string PlayerName; 
     public Vector2 AvatarPosition; 
     public int Level; 
     public int Score; 
     public List<BaseGameObject> GameObjects; 
    } 

    public class Game1 : Microsoft.Xna.Framework.Game 
    { 
     enum SavingState 
     { 
      NotSaving, 
      ReadyToSelectStorageDevice, 
      SelectingStorageDevice, 

      ReadyToOpenStorageContainer, // once we have a storage device start here 
      OpeningStorageContainer, 
      ReadyToSave 
     } 

     GraphicsDeviceManager graphics; 
     KeyboardState oldKeyboardState; 
     KeyboardState currentKeyboardState; 
     StorageDevice storageDevice; 
     SavingState savingState = SavingState.NotSaving; 
     IAsyncResult asyncResult; 
     PlayerIndex playerIndex = PlayerIndex.One; 
     StorageContainer storageContainer; 
     string filename = "savegame.sav"; 

     SaveGameData saveGameData = new SaveGameData() 
     { 
      PlayerName = "Grunt", 
      AvatarPosition = new Vector2(10, 15), 
      Level = 3, 
      Score = 99424, 
      GameObjects = new List<BaseGameObject>() 
      { 
       new Soldier { Health = 10.0f, Position = new Vector3(0.0f, 10.0f, 0.0f) }, 
       new Grenade { TimeToDetonate = 3.0f, Position = new Vector3(4.0f, 3.0f, 0.0f) } 
      } 
     }; 

     public Game1() 
     { 
      graphics = new GraphicsDeviceManager(this); 
      Content.RootDirectory = "Content"; 

#if XBOX 
      Components.Add(new GamerServicesComponent(this)); 
#endif 

      currentKeyboardState = Keyboard.GetState(); 
     } 

     protected override void Update(GameTime gameTime) 
     { 
      if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) 
       this.Exit(); 

      oldKeyboardState = currentKeyboardState; 
      currentKeyboardState = Keyboard.GetState(); 

      UpdateSaveKey(Keys.F1); 
      UpdateSaving(); 

      base.Update(gameTime); 
     } 

     private void UpdateSaveKey(Keys saveKey) 
     { 
      if (!oldKeyboardState.IsKeyDown(saveKey) && currentKeyboardState.IsKeyDown(saveKey)) 
      { 
       if (savingState == SavingState.NotSaving) 
       { 
        savingState = SavingState.ReadyToOpenStorageContainer; 
       } 
      } 
     } 

     private void UpdateSaving() 
     { 
      switch (savingState) 
      { 
       case SavingState.ReadyToSelectStorageDevice: 
#if XBOX 
        if (!Guide.IsVisible) 
#endif 
        { 
         asyncResult = StorageDevice.BeginShowSelector(playerIndex, null, null); 
         savingState = SavingState.SelectingStorageDevice; 
        } 
        break; 

       case SavingState.SelectingStorageDevice: 
        if (asyncResult.IsCompleted) 
        { 
         storageDevice = StorageDevice.EndShowSelector(asyncResult); 
         savingState = SavingState.ReadyToOpenStorageContainer; 
        } 
        break; 

       case SavingState.ReadyToOpenStorageContainer: 
        if (storageDevice == null || !storageDevice.IsConnected) 
        { 
         savingState = SavingState.ReadyToSelectStorageDevice; 
        } 
        else 
        { 
         asyncResult = storageDevice.BeginOpenContainer("Game1StorageContainer", null, null); 
         savingState = SavingState.OpeningStorageContainer; 
        } 
        break; 

       case SavingState.OpeningStorageContainer: 
        if (asyncResult.IsCompleted) 
        { 
         storageContainer = storageDevice.EndOpenContainer(asyncResult); 
         savingState = SavingState.ReadyToSave; 
        } 
        break; 

       case SavingState.ReadyToSave: 
        if (storageContainer == null) 
        { 
         savingState = SavingState.ReadyToOpenStorageContainer; 
        } 
        else 
        { 
         try 
         { 
          DeleteExisting(); 
          Save(); 
         } 
         catch (IOException e) 
         { 
          // Replace with in game dialog notifying user of error 
          Debug.WriteLine(e.Message); 
         } 
         finally 
         { 
          storageContainer.Dispose(); 
          storageContainer = null; 
          savingState = SavingState.NotSaving; 
         } 
        } 
        break; 
      } 
     } 

     private void DeleteExisting() 
     { 
      if (storageContainer.FileExists(filename)) 
      { 
       storageContainer.DeleteFile(filename); 
      } 
     } 

     private void Save() 
     { 
      using (Stream stream = storageContainer.CreateFile(filename)) 
      { 
       XmlSerializer serializer = new XmlSerializer(typeof(SaveGameData)); 
       serializer.Serialize(stream, saveGameData); 
      } 
     } 

     protected override void Draw(GameTime gameTime) 
     { 
      GraphicsDevice.Clear(Color.CornflowerBlue); 

      base.Draw(gameTime); 
     } 
    } 
} 
+1

Perfecto. Muchas gracias. Esto es exactamente de lo que necesitaba trabajar. –

+1

¿No debería cerrarse la secuencia después de guardar? –

+1

La secuencia está encapsulada en un bloque de uso que llamará IDisposable. Deséchelo en la secuencia al final del bloque. Esto ocurrirá incluso si se lanza una excepción dentro del bloque, por lo que es más seguro que llamar a Cerrar. – Empyrean

Cuestiones relacionadas