2010-09-16 16 views
6

Sto provando a lavorare sulla documentazione XNA MSDN per salvare e leggere i dati di gioco, e non ho molta fortuna.Qual è un buon esempio di salvataggio dei dati di gioco in XNA 4.0?

In sostanza, ho una classe manager che tiene traccia di più istanze di classi base.

Desidero poter salvare lo stato dell'intero elenco di oggetti di cui il gestore tiene traccia, quindi caricarli nella prossima volta che il gioco viene caricato. Salvando fondamentalmente lo stato del mondo.

risposta

15

Se si utilizza XmlSerializer come illustrato nella guida di XNA 4.0, le classi di base devono avere l'attributo [XmlInclude (Tipo)] specificato per ciascun tipo di calcestruzzo su cui possono essere serializzati.

Di seguito è riportato un esempio di come salvare i dati di gioco in XNA 4.0. Premi F1 per salvare una volta che il gioco è in esecuzione. I dati verranno salvati in una posizione simile a C: \ Users \ {username} \ Documents \ SavedGames \ WindowsGame \ Game1StorageContainer \ Player1.

Il caricamento dei dati è di nuovo un processo molto simile.

Per ottenere questo funzionamento su XBox, aggiungere riferimenti 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

Perfetto. Grazie mille. Questo è esattamente ciò di cui avevo bisogno per lavorare. –

+1

Non dovrebbe essere chiuso lo stream dopo aver salvato? –

+1

Lo stream è incapsulato in un blocco using che chiamerà IDisposable.Dispose sul flusso alla fine del blocco. Ciò si verificherà anche se viene generata un'eccezione all'interno del blocco, quindi è più sicuro che chiamare semplicemente Chiudi. – Empyrean

Problemi correlati