3
\$\begingroup\$

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?

\$\endgroup\$

4 Answers 4

8
\$\begingroup\$

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<MyGameObject>
--Paddle : MyPlaceClass
--Ball : MyBallClass
--Blocks : List<MyBLockClass>
---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:

  1. Call some custom Reinitialize method that gives the object enough info so that they can reconstructed missing references themselves.
  2. Use proxyclasses that themselves can recreated the real object
  3. 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

\$\endgroup\$
2
  • \$\begingroup\$ @JonathanHobbs your comment really needs to be an answer \$\endgroup\$
    – ashes999
    May 17, 2012 at 13:31
  • \$\begingroup\$ excellent answer. Just wanted to add in the paths: using System.IO; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; \$\endgroup\$ Jul 6, 2014 at 16:26
9
\$\begingroup\$

If you serialise an object then change its class's definition, you will not be able to recreate that object, meaning changes to your game will invalidate past saves. So whilst serialisation is definitely the simplest method, it has this flaw.

A more robust method for a game that will be changed is a manual sort of serialisation where you determine what variables are important to save, and save them - and when you recreate your objects, create them with those variables. The end result is you don't depend on serialisation, and changes to your class definitions do not invalidate past serialised data, allowing changes to your game to operate on old saves.

\$\endgroup\$
2
  • 2
    \$\begingroup\$ +1 serialization is quick but dirty, very dirty -- it may haunt you later. \$\endgroup\$
    – ashes999
    May 17, 2012 at 18:31
  • 1
    \$\begingroup\$ Been exactly in that situation, creating a space strategy game with tons of classes and properties. A save that it turns obsolete kills days of play time of the player, I say that you are very true. If the game is simple and saves do not really matter, only then serialization is an option. \$\endgroup\$ Aug 25, 2022 at 14:35
0
\$\begingroup\$

You could save the objects to disk using DataContractSerializer. You can then when the game resumes/restarts simply load them up and continue.

\$\endgroup\$
1
  • \$\begingroup\$ Why a DataContractSerializer and not a normal XMLSerializer? \$\endgroup\$
    – Roy T.
    May 16, 2012 at 19:48
0
\$\begingroup\$

The problem with using any "native" serialization capability is that it's very fragile across versions of the program. Saved state from one build is likely to be invalid for the next. It won't be comprehensible by humans or modifiable by anyone, which makes debugging problems with reloading a game a nightmare.

It's a little more work, but many valuable capabilities come from having an explicit representation of the game state, or of the steps (ie: moves) needed to construct that state. You can save and replay games, allow spectators to join at will, reconnect disconnected players, and support multiple platforms with different implementation technology.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .