2010-09-16 31 views
6

Tôi đang cố gắng để làm việc theo cách của tôi thông qua các tài liệu MSNA XNA về tiết kiệm và đọc dữ liệu trò chơi, và tôi không có nhiều may mắn.Ví dụ về lưu dữ liệu trò chơi trong XNA 4.0 là gì?

Về bản chất, tôi có một lớp người quản lý theo dõi nhiều phiên bản của các lớp cơ sở.

Tôi muốn có thể lưu trạng thái của toàn bộ danh sách đối tượng mà người quản lý theo dõi rồi tải chúng trong lần tải trò chơi tiếp theo. Về cơ bản tiết kiệm trạng thái của thế giới.

Trả lời

15

Nếu bạn sử dụng XmlSerializer như được trình bày trong trợ giúp XNA 4.0, các lớp cơ sở cần có thuộc tính [XmlInclude (Type)] được chỉ định cho từng loại cụ thể mà chúng có thể được nối tiếp vào.

Dưới đây là ví dụ về cách lưu dữ liệu trò chơi trong XNA 4.0. Nhấn F1 để lưu khi trò chơi đang chạy. Dữ liệu sẽ được lưu vào một vị trí tương tự như C: \ Users \ {username} \ Documents \ SavedGames \ WindowsGame \ Game1StorageContainer \ Player1.

Tải lại dữ liệu là một quá trình rất giống nhau.

Để làm việc này trên XBox, hãy thêm tham chiếu đến 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

Hoàn hảo. Cảm ơn nhiều. Đây chính xác là những gì tôi cần để làm việc. –

+1

Không nên đóng luồng sau khi lưu? –

+1

Luồng được gói gọn trong một khối sử dụng sẽ gọi IDisposable.Dispose trên luồng ở cuối khối. Điều này sẽ xảy ra ngay cả khi một ngoại lệ được ném vào trong khối để an toàn hơn là chỉ gọi Close. – Empyrean

Các vấn đề liên quan