So I am currently working on a simple game project that most people start of with: "breakout". part of my goal is to make a gamesave of the current gamestate the simplest way possible.
For example, lets say I lose the game or I want to exit the game. Then later, I want to reload the gamestate to the same position of the paddle, ball and bricks. The only problem is I have multiple forms and I just want to save this specific form in its specific state.
I have an idea on how to approach (I would find a way to save the position of the paddle, ball and the bricks and that exact time) just I have no clue how I would execute it. How can I achieve this?
Answer
With C# (and many other languages) you can serialize (aka save) the state of a objects directly to a file and de-serialize (aka re-instantiate/load) them later so that you have the same objects with the same state.
This works best if you have a prober scenegraph because this way it will happen almost automatically in C#.
As an example say I have the following scenegraph
Root : MyRootClass
-Score : int
-WorldObjects : List
--Paddle : MyPlaceClass
--Ball : MyBallClass
--Blocks : List
---BlockA : MyBlockClass
---BlockB : MyBlockClass
---BLockEtc
You should decorate all of the above classes (except List and int which aren't yours of course) with the [Serializable()]
attribute and any fields in them which you do not wish to save or load (say references to a graphics device or something) should be marked with the [NonSerializable()]
attribute
You can then use the BinaryFormatter to serialize ONLY the the root object to a file, since all other elements are referenced by the root object they will also be serialized.
FileStream fs = new FileStream("DataFile.dat", FileMode.Create);
// Construct a BinaryFormatter and use it to serialize the data to the stream.
BinaryFormatter formatter = new BinaryFormatter();
try
{
formatter.Serialize(fs, root);
}
catch (SerializationException e)
{
Console.WriteLine("Failed to serialize. Reason: " + e.Message);
throw;
}
finally
{
fs.Close();
}
In the same fashion you can load the root object again:
FileStream fs = new FileStream("DataFile.dat", FileMode.Open);
try
{
BinaryFormatter formatter = new BinaryFormatter();
// Deserialize the hashtable from the file and
// assign the reference to the local variable.
addresses = (Hashtable) formatter.Deserialize(fs);
}
catch (SerializationException e)
{
Console.WriteLine("Failed to deserialize. Reason: " + e.Message);
throw;
}
finally
{
fs.Close();
}
Now if you're lucky all the objects that you wanted to serialize only references objects that can be serialized, if you're not so lucky you need a way to fix those references. There are multiple ways to do this:
- Call some custom Reinitialize method that gives the object enough info so that they can reconstructed missing references themselves.
- Use proxyclasses that themselves can recreated the real object
- Fix the serializable part of your game to not have these references (probably the best idea)
A good example of references that can't be serialized/deserialized and thus need one fo the above solutions is a references to the graphics device.
Also note that C# can, out of the box, can also serialize to human readable formats instead of just binary, for example INI, XML and JSON. See this for a small reference.
Finally if you're using XNA and what to serialize data on the Xbox or WP7 you should take a look at this resource.
Note I've added two links to my own blog because they seemed appropriate references however it would be better to replace them with more expert material so feel free to edit them with better links
No comments:
Post a Comment