Saving and serialization

  • (2 Pages)
  • +
  • 1
  • 2

25 Replies - 7050 Views - Last Post: 24 March 2011 - 07:00 AM

#1 ShadowsEdge19  Icon User is offline

  • D.I.C Addict

Reputation: 142
  • View blog
  • Posts: 664
  • Joined: 16-January 10

Saving and serialization

Posted 22 March 2011 - 08:57 AM

Hi guys, I've been researching how to save my level editor's files and I'm still not sure how to do this for a PC application and not a 360 using storage devices, all I want is to save a single object: Tile[,]. Tile itself contains which contains a single int value.

I need to also be able to dynamically save each file as different names in ascending numerical order without repeats, so Level1, Level2, Level3...etc.

I also need to choose which file to load somehow.

Plus these same files are going to be automatically loaded one at a time in another application that will be playable on the 360 so I need it to be compatible, there won't be any need to save in the main game just load.

Can anyone help me out?

This post has been edited by ShadowsEdge19: 22 March 2011 - 08:58 AM


Is This A Good Question/Topic? 0
  • +

Replies To: Saving and serialization

#2 SixOfEleven  Icon User is offline

  • using Caffeine;
  • member icon

Reputation: 945
  • View blog
  • Posts: 6,342
  • Joined: 18-October 08

Re: Saving and serialization

Posted 22 March 2011 - 10:25 AM

I posted a reply about this in another topic.

Quote

The best approach I've found is to using the Intermediate Serializer and serialize your your custom content to an XML file. What I do is create a game library that holds the custom data type I want to use. I then create a project for the editor. I add a reference to the game library to the editor and a reference to the Xna.Framework.Content.Pipeline. You will have to change the target framework of the editor to support the full version of the .NET Framework you are targeting to get that reference to appear in the .NET tab. If you actually want to use XNA inside of the editor there is a code sample on App Hub for hosting XNA inside of a Windows Forms application. If you want a more in depth explanation of the process let me know and I can link you to a couple tutorials that I've written on my site about loading custom content.

Was This Post Helpful? 0
  • +
  • -

#3 ShadowsEdge19  Icon User is offline

  • D.I.C Addict

Reputation: 142
  • View blog
  • Posts: 664
  • Joined: 16-January 10

Re: Saving and serialization

Posted 22 March 2011 - 10:38 AM

View PostSixOfEleven, on 22 March 2011 - 10:25 AM, said:

I posted a reply about this in another topic.

Quote

The best approach I've found is to using the Intermediate Serializer and serialize your your custom content to an XML file. What I do is create a game library that holds the custom data type I want to use. I then create a project for the editor. I add a reference to the game library to the editor and a reference to the Xna.Framework.Content.Pipeline. You will have to change the target framework of the editor to support the full version of the .NET Framework you are targeting to get that reference to appear in the .NET tab. If you actually want to use XNA inside of the editor there is a code sample on App Hub for hosting XNA inside of a Windows Forms application. If you want a more in depth explanation of the process let me know and I can link you to a couple tutorials that I've written on my site about loading custom content.


Have you got a link for those tutorials you mention here?

Will I need to use the storage device containers? If so then I can access the FileExists method in order to create dynamically named files.
Was This Post Helpful? 0
  • +
  • -

#4 SixOfEleven  Icon User is offline

  • using Caffeine;
  • member icon

Reputation: 945
  • View blog
  • Posts: 6,342
  • Joined: 18-October 08

Re: Saving and serialization

Posted 22 March 2011 - 10:47 AM

No, you won't need to use storage to load the content. You add them as game content and the can be read in using the Content.Load<T> method. They are part of my XNA 4.0 RPG series but I'm sure you can see what is going on.

Creating an editor and serializing custom content
http://xnagpa.net/xn...tutorial11a.pdf
http://xnagpa.net/xn...tutorial11b.pdf
http://xnagpa.net/xn...tutorial11c.pdf

More on the editors
http://xnagpa.net/xn...tutorial14a.pdf
http://xnagpa.net/xn...tutorial14b.pdf

Reading your data in as custom content
http://xnagpa.net/xn...gtutorial22.pdf

Creating a level editor that uses XNA
http://xnagpa.net/xn...tutorial23A.pdf
http://xnagpa.net/xn...tutorial23B.pdf
http://xnagpa.net/xn...gtutorial24.pdf
http://xnagpa.net/xn...gtutorial25.pdf
Was This Post Helpful? 0
  • +
  • -

#5 ShadowsEdge19  Icon User is offline

  • D.I.C Addict

Reputation: 142
  • View blog
  • Posts: 664
  • Joined: 16-January 10

Re: Saving and serialization

Posted 22 March 2011 - 01:04 PM

Sorry but your RPG Editor tutorial is of a far greater complexity than what I hope to achieve and it's quite difficult to pick and choose the parts I need to make serialization work for my much simpler level editor.

So I found this article on Intermediate Serialization and I'm trying to make my game compatible but even with Game Studio 4.0 installed I can't find the Microsoft.Xna.Framework.Content.Pipeline assembly in the References library, therefore I can't link to the Microsoft.Xna.Framework.Content.Pipeline.Serialization.Intermediate namespace either.
Was This Post Helpful? 0
  • +
  • -

#6 ShadowsEdge19  Icon User is offline

  • D.I.C Addict

Reputation: 142
  • View blog
  • Posts: 664
  • Joined: 16-January 10

Re: Saving and serialization

Posted 22 March 2011 - 01:12 PM

I just realized that they don't include that namespace in 4.0 anymore but I found a related thread that solves the issue, however the only problem is I am not allowed to change the Target Framework in the Properties, it's just greyed out and I can't selected anything from it.

This post has been edited by ShadowsEdge19: 22 March 2011 - 01:13 PM

Was This Post Helpful? 0
  • +
  • -

#7 lesPaul456  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 173
  • View blog
  • Posts: 729
  • Joined: 16-April 09

Re: Saving and serialization

Posted 22 March 2011 - 02:34 PM

Are you trying to change the target framework for a Xbox 360 project? Since Xbox 360 applications use the .NET Compact Framework only, that box will be disabled.
Was This Post Helpful? 0
  • +
  • -

#8 ShadowsEdge19  Icon User is offline

  • D.I.C Addict

Reputation: 142
  • View blog
  • Posts: 664
  • Joined: 16-January 10

Re: Saving and serialization

Posted 22 March 2011 - 03:45 PM

No I've got it set as a WindowsGame, and just to make sure I created a brand new Windows game and added the Content.Pipeline.dll to the References and the Target Framework is still inaccessible.
Was This Post Helpful? 0
  • +
  • -

#9 SixOfEleven  Icon User is offline

  • using Caffeine;
  • member icon

Reputation: 945
  • View blog
  • Posts: 6,342
  • Joined: 18-October 08

Re: Saving and serialization

Posted 22 March 2011 - 04:39 PM

You need to create a separate project, a Windows Forms project, to be able to select the proper .NET Framework. The IntermidateSerliaizer isn't available inside of an XNA project. Another option that you have available to you is to create a custom file format and then create a Content Pipeline Extension project. Loading a custom content can be quite complicated, no matter what approach you take. If you were to try using Title Storage from the Storage classes that will be complicated as well.

The basic approach for using the IntermediateSerializer is this:

1. Create your XNA game.
2. Add a library, XNA Game Library or other Library, to the solution that holds the content classes.
3. Add the reference to the library to your XNA game.
4. Add a reference of the library to the content project/folder.
4. Add a new project to the solution that will act as your editor.
5. Set the target of the project to the full framework.
6. Reference the Xna.Framework.Content.Pipeline in that project.
7. Add a reference to the library you created to the editor.
8. Serialize the object from the editor.
9. Add the files to Content.
10. Read them using Content.Load<T>

*edit*
You can also do a Console project.
Was This Post Helpful? 0
  • +
  • -

#10 ShadowsEdge19  Icon User is offline

  • D.I.C Addict

Reputation: 142
  • View blog
  • Posts: 664
  • Joined: 16-January 10

Re: Saving and serialization

Posted 22 March 2011 - 05:05 PM

I've been trying a different approach using the Storage Serialization method in the Storage Demo Project from the MSDN site. I've so far got this:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BlockableLevelEditor
{
    public class LevelGrid
    {
        private Tile[,] grid;

        public Tile[,] Grid { get { return grid; } set { grid = value; } }

        public LevelGrid()
        {
            grid = new Tile[10, 10];
        }
    }
}




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


namespace BlockableLevelEditor
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class LevelEditor : Microsoft.Xna.Framework.Game
    {
        LevelGrid levelGrid;

        Button newLevelButton;
        Button saveLevelButton;
        Button loadLevelButton;
        Button quitButton;

        bool aPressed = false;
        bool bPressed = false;
        bool leftPressed = false;
        bool rightPressed = false;
        bool upPressed = false;
        bool downPressed = false;
        bool enterKeyPressed = false;
        bool leftKeyPressed = false;
        bool rightKeyPressed = false;
        bool upKeyPressed = false;
        bool downKeyPressed = false;
        bool gameSaveRequested = false;

        private GamePadState oldGamepadState;
        private KeyboardState oldKeyboardState;

        private MouseState currentMouseState;
        private MouseState lastMouseState;

        StorageDevice device;
        IAsyncResult result;

        [Serializable]
        public struct SaveGameData
        {
            public LevelGrid gameGrid;
        }

        public LevelEditor()
        {
            newLevelButton = new Button(new Vector2(900, 50));
            saveLevelButton = new Button(new Vector2(900, 100));
            loadLevelButton = new Button(new Vector2(900, 150));
            quitButton = new Button(new Vector2(900, 650));

            currentMouseState = new MouseState();
            lastMouseState = new MouseState();
        }

        public void LoadLevel()
        { 
        
        }

        public void SaveLevel(StorageDevice device)
        {
            // Create the data to save.
            SaveGameData data = new SaveGameData();
            data.gameGrid = levelGrid;

            // Open a storage container.
            IAsyncResult result =
                device.BeginOpenContainer("StorageDemo", null, null);

            // Wait for the WaitHandle to become signaled.
            result.AsyncWaitHandle.WaitOne();

            StorageContainer container = device.EndOpenContainer(result);

            // Close the wait handle.
            result.AsyncWaitHandle.Close();

            string filename = "savegame.sav";

            // Check to see whether the save exists.
            if (container.FileExists(filename))
                // Delete it so that we can create one fresh.
                container.DeleteFile(filename);

            // Create the file.
            Stream stream = container.CreateFile(filename);

            // Convert the object to XML data and put it in the stream.
            XmlSerializer serializer = new XmlSerializer(typeof(SaveGameData));
            serializer.Serialize(stream, data);

            // Close the file.
            stream.Close();

            // Dispose the container, to commit changes.
            container.Dispose();
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            base.Update(gameTime);

            UpdateControls();
      
            //Updates the previous mouse state;
            lastMouseState = currentMouseState;

            //Updates to the newest mouse state
            currentMouseState = Mouse.GetState();

            newLevelButton.Update();
            saveLevelButton.Update();
            loadLevelButton.Update();
            quitButton.Update();

            //Deal with the user input
            HandleInput();

            // If a save is pending, save as soon as the
            // storage device is chosen
            if ((gameSaveRequested) && (result.IsCompleted))
            {
                StorageDevice device = StorageDevice.EndShowSelector(result);
                if (device != null && device.IsConnected)
                {
                    SaveLevel(device);

                }
                // Reset the request flag
                gameSaveRequested = false;
            }
        }

        public void UpdateControls()
        {
            GamePadState pad = GamePad.GetState(PlayerIndex.One);
            KeyboardState keyBoard = Keyboard.GetState();

            aPressed = (pad.Buttons.A == ButtonState.Pressed && pad.Buttons.A != oldGamepadState.Buttons.A);
            bPressed = (pad.Buttons.B == ButtonState.Pressed && pad.Buttons.B != oldGamepadState.Buttons.B)/>;
            leftPressed = (pad.DPad.Left == ButtonState.Pressed && pad.DPad.Left != oldGamepadState.DPad.Left);
            rightPressed = (pad.DPad.Right == ButtonState.Pressed && pad.DPad.Right != oldGamepadState.DPad.Right);
            upPressed = (pad.DPad.Up == ButtonState.Pressed && pad.DPad.Up != oldGamepadState.DPad.Up);
            downPressed = (pad.DPad.Down == ButtonState.Pressed && pad.DPad.Down != oldGamepadState.DPad.Down);

            enterKeyPressed = (keyBoard.IsKeyDown(Keys.Enter) && keyBoard != oldKeyboardState);
            leftKeyPressed = (keyBoard.IsKeyDown(Keys.Left) && keyBoard != oldKeyboardState);
            rightKeyPressed = (keyBoard.IsKeyDown(Keys.Right) && keyBoard != oldKeyboardState);
            upKeyPressed = (keyBoard.IsKeyDown(Keys.Up) && keyBoard != oldKeyboardState);
            downKeyPressed = (keyBoard.IsKeyDown(Keys.Down) && keyBoard != oldKeyboardState);

            oldGamepadState = pad;
            oldKeyboardState = keyBoard;
        }

        public void HandleInput()
        {
            MouseState mouse = Mouse.GetState();
            Tile newTile;

            if (cursor.Selected)
            {
                for(int i = 0; i < texButtons.Count; i++)
                {
                    if (texButtons[i].Bounds.Contains(mouse.X, mouse.Y))
                    {
                        if ((currentMouseState.LeftButton == ButtonState.Released
                            && lastMouseState.LeftButton == ButtonState.Pressed) || aPressed)
                        {
                            newTile = new Tile(i);
                            levelGrid.Grid[cursor.Row, cursor.Col] = newTile;
                            levelGrid.Grid[cursor.Row, cursor.Col].LoadContent(Content);
                            cursor.Selected = false;
                        } 
                    }
                }
            }

            #region New Level Button

            #endregion

            #region Save Level Button

            if ((saveLevelButton.Bounds.Contains(mouse.X, mouse.Y)) || aPressed)
            {
                // Was the button pressed?
                if (currentMouseState.LeftButton == ButtonState.Released &&
                   lastMouseState.LeftButton == ButtonState.Pressed)
                {

                    // Set the request flag
                    if (gameSaveRequested == false)
                    {
                        gameSaveRequested = true;
                        result = StorageDevice.BeginShowSelector(
                                PlayerIndex.One, null, null);
                    }
                }
            }

            #endregion   

            #region Load Level Button

            if ((loadLevelButton.Bounds.Contains(mouse.X, mouse.Y)) || aPressed)
            {
                // Was the button pressed?
                if (currentMouseState.LeftButton == ButtonState.Released &&
                   lastMouseState.LeftButton == ButtonState.Pressed)
                {
                    LoadLevel();
                }
            }

            #endregion   

            #region Quit Game Button

            if ((quitButton.Bounds.Contains(mouse.X, mouse.Y)) || aPressed)
            {
                // Was the button pressed?
                if (currentMouseState.LeftButton == ButtonState.Released &&
                   lastMouseState.LeftButton == ButtonState.Pressed)
                {
                    this.Exit();
                }
            }

            #endregion
        }
    }
}



I get an error reflecting type 'BlockableLevelEditor.LevelEditor.SaveGameData' at the line:

XmlSerializer serializer = new XmlSerializer(typeof(SaveGameData)); in SaveLevel();

System.InvalidOperationException was unhandled
  Message=There was an error reflecting type 'BlockableLevelEditor.LevelEditor.SaveGameData'.
  Source=System.Xml
  StackTrace:
       at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
       at System.Xml.Serialization.XmlReflectionImporter.ImportElement(TypeModel model, XmlRootAttribute root, String defaultNamespace, RecursionLimiter limiter)
       at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(Type type, XmlRootAttribute root, String defaultNamespace)
       at System.Xml.Serialization.XmlSerializer..ctor(Type type, String defaultNamespace)
       at System.Xml.Serialization.XmlSerializer..ctor(Type type)
       at BlockableLevelEditor.LevelEditor.SaveLevel(StorageDevice device) in C:\Users\********\Documents\Visual Studio 2010\Projects\BlockableLevelEditor\BlockableLevelEditor\LevelEditor.cs:line 260
       at BlockableLevelEditor.LevelEditor.Update(GameTime gameTime) in C:\Users\********\Documents\Visual Studio 2010\Projects\BlockableLevelEditor\BlockableLevelEditor\LevelEditor.cs:line 304
       at Microsoft.Xna.Framework.Game.Tick()
       at Microsoft.Xna.Framework.Game.HostIdle(Object sender, EventArgs e)
       at Microsoft.Xna.Framework.GameHost.OnIdle()
       at Microsoft.Xna.Framework.WindowsGameHost.RunOneFrame()
       at Microsoft.Xna.Framework.WindowsGameHost.ApplicationIdle(Object sender, EventArgs e)
       at System.Windows.Forms.Application.ThreadContext.System.Windows.Forms.UnsafeNativeMethods.IMsoComponent.FDoIdle(Int32 grfidlef)
       at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.Run(Form mainForm)
       at Microsoft.Xna.Framework.WindowsGameHost.Run()
       at Microsoft.Xna.Framework.Game.RunGame(Boolean useBlockingRun)
       at Microsoft.Xna.Framework.Game.Run()
       at BlockableLevelEditor.Program.Main(String[] args) in C:\Users\S********\Documents\Visual Studio 2010\Projects\BlockableLevelEditor\BlockableLevelEditor\Program.cs:line 14
  InnerException: System.InvalidOperationException
       Message=There was an error reflecting field 'gameGrid'.
       Source=System.Xml
       StackTrace:
            at System.Xml.Serialization.XmlReflectionImporter.InitializeStructMembers(StructMapping mapping, StructModel model, Boolean openModel, String typeName, RecursionLimiter limiter)
            at System.Xml.Serialization.XmlReflectionImporter.ImportStructLikeMapping(StructModel model, String ns, Boolean openModel, XmlAttributes a, RecursionLimiter limiter)
            at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
       InnerException: System.InvalidOperationException
            Message=There was an error reflecting type 'BlockableLevelEditor.LevelGrid'.
            Source=System.Xml
            StackTrace:
                 at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
                 at System.Xml.Serialization.XmlReflectionImporter.ImportAccessorMapping(MemberMapping accessor, FieldModel model, XmlAttributes a, String ns, Type choiceIdentifierType, Boolean rpc, Boolean openModel, RecursionLimiter limiter)
                 at System.Xml.Serialization.XmlReflectionImporter.ImportFieldMapping(StructModel parent, FieldModel model, XmlAttributes a, String ns, RecursionLimiter limiter)
                 at System.Xml.Serialization.XmlReflectionImporter.InitializeStructMembers(StructMapping mapping, StructModel model, Boolean openModel, String typeName, RecursionLimiter limiter)
            InnerException: System.InvalidOperationException
                 Message=Cannot serialize member 'BlockableLevelEditor.LevelGrid.Grid' of type 'BlockableLevelEditor.Tile[,]', see inner exception for more details.
                 Source=System.Xml
                 StackTrace:
                      at System.Xml.Serialization.StructModel.CheckSupportedMember(TypeDesc typeDesc, MemberInfo member, Type type)
                      at System.Xml.Serialization.StructModel.GetPropertyModel(PropertyInfo propertyInfo)
                      at System.Xml.Serialization.StructModel.GetFieldModel(MemberInfo memberInfo)
                      at System.Xml.Serialization.XmlReflectionImporter.InitializeStructMembers(StructMapping mapping, StructModel model, Boolean openModel, String typeName, RecursionLimiter limiter)
                      at System.Xml.Serialization.XmlReflectionImporter.ImportStructLikeMapping(StructModel model, String ns, Boolean openModel, XmlAttributes a, RecursionLimiter limiter)
                      at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
                 InnerException: System.NotSupportedException
                      Message=Cannot serialize object of type BlockableLevelEditor.Tile[,]. Multidimensional arrays are not supported.
                      InnerException: 


Was This Post Helpful? 0
  • +
  • -

#11 lesPaul456  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 173
  • View blog
  • Posts: 729
  • Joined: 16-April 09

Re: Saving and serialization

Posted 22 March 2011 - 05:51 PM

XmlSerializer doesn't serialize multi-dimensional arrays. You could try using jagged arrays instead, although that may not be practical for your design. You could also just use the BinaryFormatter, found in the Runtime.Serialization.Formatters.Binary namespace, which I know for a fact can handle multi-dimensional arrays.

This post has been edited by lesPaul456: 22 March 2011 - 05:52 PM

Was This Post Helpful? 1
  • +
  • -

#12 SixOfEleven  Icon User is offline

  • using Caffeine;
  • member icon

Reputation: 945
  • View blog
  • Posts: 6,342
  • Joined: 18-October 08

Re: Saving and serialization

Posted 22 March 2011 - 05:58 PM

An alternative that I've used is to have a data class for reading/writing that has a single dimensional array and a static method in the class that is in the game for the data.

public class MapData
{
   public Tile[] Tiles;
   public int Width;
   public int Height;
}

public class Map
{
   Tile[,] tiles;

   public static void FromMapData(MapData data)
   {
      tiles = new Tile[data.Height, data.Width];

      for (int y = 0; y < data.Height; y++)
         for (int x = 0; x < data.Width; x++)
           tiles[y, x] = data.Tiles[y * data.Width + x];
   }
}



*edit*
You can also include a ToMapData method will return a map.

This post has been edited by SixOfEleven: 22 March 2011 - 05:59 PM

Was This Post Helpful? 0
  • +
  • -

#13 ShadowsEdge19  Icon User is offline

  • D.I.C Addict

Reputation: 142
  • View blog
  • Posts: 664
  • Joined: 16-January 10

Re: Saving and serialization

Posted 22 March 2011 - 06:09 PM

I have this:

public void SaveLevel(StorageDevice device)
        {
            int i = 0;
            // Create the data to save.
            SaveGameData data = new SaveGameData();
            data.gameGrid = levelGrid.Grid;
            
            // Open a storage container.
            IAsyncResult result =
                device.BeginOpenContainer("BlockableFiles", null, null);

            // Wait for the WaitHandle to become signaled.
            result.AsyncWaitHandle.WaitOne();

            StorageContainer container = device.EndOpenContainer(result);

            // Close the wait handle.
            result.AsyncWaitHandle.Close();

            while (container.FileExists("level"+i+".sav"))
            {
                i++;
            }

            string filename = "level" + i + ".sav";

            // Create the file.
            Stream stream = container.CreateFile(filename);

            BinaryFormatter formatter = new BinaryFormatter();

            formatter.Serialize(stream, data);

            // Close the file.
            stream.Close();

            // Dispose the container, to commit changes.
            container.Dispose();
        }



I'm now getting warnings that Tile and the Vector2s I have in the Object are not marked as serializable, is there a way to get it to only choose specific parts of the object to serialize and ignore the rest? I just have 1 attribute in Tile that I want saved.
Was This Post Helpful? 0
  • +
  • -

#14 ShadowsEdge19  Icon User is offline

  • D.I.C Addict

Reputation: 142
  • View blog
  • Posts: 664
  • Joined: 16-January 10

Re: Saving and serialization

Posted 22 March 2011 - 06:43 PM

Okay I've sorted it out to serialize only an int[,] that contains the specific values I wanted from Tile[,] and I can also load the same file in.

        #region Save Level

        public void SaveLevel(StorageDevice device)
        {
            int n = 0;
            // Create the data to save.
            SaveGameData data = new SaveGameData();
            data.gameGrid = new int[10, 10];
            
            for (int i = 0; i < 9; i++)
            {
                for (int j = 0; j < 9; j++)
                {
                    data.gameGrid[i,j] = levelGrid.Grid[i,j].TexNo;
                }
            }

            // Open a storage container.
            IAsyncResult result =
                device.BeginOpenContainer("BlockableFiles", null, null);

            // Wait for the WaitHandle to become signaled.
            result.AsyncWaitHandle.WaitOne();

            StorageContainer container = device.EndOpenContainer(result);

            // Close the wait handle.
            result.AsyncWaitHandle.Close();

            while (container.FileExists("level"+n+".sav"))
            {
                n++;
            }

            string filename = "level" + n + ".sav";

            // Create the file.
            Stream stream = container.CreateFile(filename);

            BinaryFormatter formatter = new BinaryFormatter();

            formatter.Serialize(stream, data);

            // Close the file.
            stream.Close();

            // Dispose the container, to commit changes.
            container.Dispose();
        }

        #endregion

        #region Load Level

        /// <summary>
        /// This method loads a serialized data object
        /// from the StorageContainer for this game.
        /// </summary>
        /// <param name="device"></param>
        private void LoadLevel(StorageDevice device)
        {
            // Open a storage container.
            IAsyncResult result =
                device.BeginOpenContainer("BlockableFiles", null, null);

            // Wait for the WaitHandle to become signaled.
            result.AsyncWaitHandle.WaitOne();

            StorageContainer container = device.EndOpenContainer(result);

            // Close the wait handle.
            result.AsyncWaitHandle.Close();

            string filename = "level0.sav";

            // Check to see whether the save exists.
            if (!container.FileExists(filename))
            {
                // If not, dispose of the container and return.
                container.Dispose();
                return;
            }

            // Open the file.
            Stream stream = container.OpenFile(filename, FileMode.Open);

            // Read the data from the file.
            BinaryFormatter formatter = new BinaryFormatter();
          
            SaveGameData data = (SaveGameData)formatter.Deserialize(stream);

            // Close the file.
            stream.Close();

            // Dispose the container.
            container.Dispose();

            for (int i = 0; i < 10; i++)
            {
                for (int j = 0; j < 10; j++)
                {
                    levelGrid.Grid[i, j] = new Tile(data.gameGrid[i,j]);
                }
            }

            UnloadContent();
            LoadContent();

            // Report the data to the console.
            Debug.WriteLine("Loaded Level Sucessfully");
        }

        #endregion


I have it to save files in the format Level0.sav, Level1.sav, Level2.sav etc but I now need to figure out a way to receive user input to load up a specific level id, a single number, say 4 to load Level4.sav.

Will I need to have a small pop up screen with a user prompt? This can be just for a Windows Application or Windows Game since the editor is the only program that will load in this fashion.

This post has been edited by ShadowsEdge19: 22 March 2011 - 06:44 PM

Was This Post Helpful? 0
  • +
  • -

#15 Robin19  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 272
  • View blog
  • Posts: 552
  • Joined: 07-July 10

Re: Saving and serialization

Posted 23 March 2011 - 05:15 AM

string filename = string.Format("Level{0}.sav", userInput);

This will take the user input (which can be an int, string, or any object really) and put it into the string for you. You can capture the input any way you want. Just be sure to handle bad input. Either use a try catch block or call File.Exists before trying to read it.
Was This Post Helpful? 0
  • +
  • -

  • (2 Pages)
  • +
  • 1
  • 2