2010-09-16 5 views
6

Ich versuche, mich durch die XNA MSDN-Dokumentation zum Speichern und Lesen von Spieldaten zu arbeiten, und ich habe nicht viel Glück.Was ist ein gutes Beispiel für das Speichern von Spieldaten in XNA 4.0?

Im Wesentlichen habe ich eine Manager-Klasse, die mehrere Instanzen von Basisklassen verfolgt.

Ich möchte in der Lage sein, den Status der gesamten Liste der Objekte zu speichern, die der Manager verfolgt, und sie dann beim nächsten Laden des Spiels zu laden. Grundsätzlich den Zustand der Welt retten.

Antwort

15

Wenn Sie den XmlSerializer wie in der XNA 4.0-Hilfe gezeigt verwenden, müssen Basisklassen das Attribut [XmlInclude (Type)] für jeden konkreten Typ angeben, in den sie serialisiert werden können.

Im Folgenden finden Sie ein Beispiel zum Speichern von Spieldaten in XNA 4.0. Drücken Sie F1, um zu speichern, sobald das Spiel ausgeführt wird. Die Daten werden an einem ähnlichen Ort wie C: \ Users \ {Benutzername} \ Documents \ SavedGames \ WindowsGame \ Game1StorageContainer \ Player1 gespeichert.

Das erneute Laden der Daten ist ein sehr ähnlicher Prozess.

Um dies auf XBox arbeiten hinzufügen Referenzen auf 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

Perfekt. Vielen Dank. Genau davon musste ich arbeiten. –

+1

Sollte der Stream nach dem Speichern nicht geschlossen werden? –

+1

Der Stream ist in einem using-Block gekapselt, der IDisposable.Dispose im Stream am Ende des Blocks aufruft. Dies tritt auch dann auf, wenn eine Ausnahme innerhalb des Blocks ausgelöst wird, was sicherer ist, als nur Close aufzurufen. – Empyrean