2010-09-16 39 views
6

我想通過保存和閱讀遊戲數據的XNA MSDN文檔工作,而且我沒有太多的運氣。在XNA 4.0中保存遊戲數據的好例子是什麼?

在本質上我有一個管理器類以跟蹤基類的多個實例。

我希望能夠挽救這位經理是保持跟蹤對象的整個列表的狀態,然後再加載它們在接下來的時間遊戲加載。基本上拯救世界的狀態。

回答

15

如果使用XmlSerializer如圖中XNA 4.0幫助下,基類需要有[XmlInclude(類型)]爲每個具體類型可以將它們序列化到指定的屬性。

下面是如何保存在XNA 4.0遊戲數據的例子。按F1鍵以保存遊戲運行。數據將被保存到類似於C:\ Users \ {用戶名} \ Documents \ SavedGames \ WindowsGame \ Game1StorageContainer \ Player1的位置。

重新載入數據是一個非常類似的過程。

要獲得在Xbox這個工作添加引用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

完美。非常感謝你。這正是我需要解決的問題。 – 2010-09-16 22:52:53

+1

保存後不應該關閉流嗎? – 2012-02-04 01:50:25

+1

流被封裝在使用塊中,該塊將調用IDisposable.Dispose在塊末尾的流上。即使在塊內引發異常,也會發生這種情況,因此比調用Close更安全。 – Empyrean 2012-02-07 05:36:10