Game Saving/Loading

Started by
14 comments, last by ToohrVyk 16 years, 6 months ago
So I've already made a few posts trying to understand how to save structs and vectors. is it normal practice for struct saving to use ofs.write((char *)&one, sizeof(one)); when dealing with saving/loading games. or do most games write serializers? the only problem with the former that I see is if they want to send their save games to other people... basically I have 2 main questions. Do i have to serialize? (because ive looked a few examples and it looks like several hundred lines of code to make your own and I've never done it before) and if I have to serialize, how the hell do i do it? I'm using vectors that contain stucts, but I think I'm going to just loop through the vector my self and attempt to simply save the structs and not worry about the vector it's self. then when i load i can re-populate the vector. only because serializing a vector is probably 10x more code than serializing a struct, and also, some of my structs contain vectors of structs, so i would be clueless on how to serialize that correctly, or even write a template/generic serialization function that could handle it all. I'm starting to think I should just do it manually by hand and save evertyhing in a text file, even though it will take me way way longer to code(a week? for saving and loading functions?), i would understand it (the code) and can even edit the save game files outside the application.
Black Sky A Star Control 2/Elite like game
Advertisement
boost::serialization

Because ugly hacks that only do shallow copies break down very fast, and/or require all sorts of maintenance.

It's still nontrivial, nothing like the one-liner you can do with Python's pickle module. I suppose that's just the language limitations of C++.

P.S. Nifty game concept, and nice screenshots. I don't think there's been anything like Star Control 2 or Privateer since...well, SC2 and Privateer.
does boost::serialize require constructors?

I'm not using classes.
Black Sky A Star Control 2/Elite like game
would this work and be any good? or is this crap?
also is there anyway I can turn this into a template so I can use other datatypes(mystruct1, mystruct2...)

struct mystruct{
vars..
}

vector<mystruct> vi;

ofstream out("out.txt");
ostream_iterator<mystruct> oi(out, " ");

copy(vi.begin(), vi.end(), oi);

out.close();
Black Sky A Star Control 2/Elite like game
Well, you may not be using your own classes, but you are using classes. The big deal about serialization is that just writing something like 'ofs.write((char*)&one,sizeof(one))' [which by the way, is a method of serialization, though not a particularly robust one] rarely stores just the right amount of information. For every pointer you have, that method will save an address [extra information] and not the data the pointer points to [too little information]. There may also be data that you want to store in run-time but not in the save [or the other way around], like for example a running sum of some other numbers [which will be faster to recompute than to read from disk]. There are also instances when you may be storing information that is only immediately useful [like a timestamp, which is meaningless when you reload the structure 4 weeks later].

There are the things that cause people to concern themselves with implementing a robust and controlled way of serializing.

As far as how to do it, it's often something that is sewn into the various classes. If you absolutely insist on not using classes [by the way, structs are pretty similar to classes in c++. Very, very similar. Matter of fact, you could write member functions and such into structs, which makes the following recommendation moot. But this is a 'straight C' way to do it.], you could technically have the first data member of all of your structs be a pointer to a function that does the serialization, thus you just pass the struct via pointer to a function that casts the struct to a serialization pointer and passes the struct address to it. Seriously though, this is re-inventing the wheel [and crafting that wheel out of hand grenades and uncut 6-pack plastic rings]. The only reason I'm even typing this is because you asked how to do it the ol' fashion way, which was awful [thus the reason why it's the old fashion way, and not the new hip way]. You're using a powerful language, use it's power, and don't imprison yourself by refusing to use certain features that were provided for a good reason.
Quote:Original post by drakostar
It's still nontrivial, nothing like the one-liner you can do with Python's pickle module.


A common misconception. If you just pickle an object to save it, it will bring all its references along. Some of these might be wanted (other entities, transform matrix, and so on) while others are actually quite unwanted (the OpenGL context, the texture data, the networking sockets, and so on), which forces you to discriminate over what every object is allowed to reference just so that it serializes correctly.

I'm using O'Caml myself, which also has a serialization module (Marshal) and still writing my own serialization system for performance, compression and especially reference-discrimination issues.

if I used ostream_iterator i would have to overload operators for each struct/class so that sounds like a really bad idea.

anyone have a really easy to understand serialization tutorial for boost or something even easier than that?
Black Sky A Star Control 2/Elite like game
Quote:Original post by ToohrVyk
A common misconception. If you just pickle an object to save it, it will bring all its references along. Some of these might be wanted (other entities, transform matrix, and so on) while others are actually quite unwanted (the OpenGL context, the texture data, the networking sockets, and so on)

Why would you have any of that mixed in with your game world representation? Good OO practice and/or a proper multi-threaded game engine requires an independent model, from which the representations in the renderer, physics engine, etc. are derived. There are a number of threads in the OGRE forums discussing this kind of engine and its implementation at length, if you think that's too idealistic. No, I'm quite happy with the one-liner.
Quote:if I used ostream_iterator i would have to overload operators for each struct/class so that sounds like a really bad idea.
anyone have a really easy to understand serialization tutorial for boost or something even easier than that?


In C++, you will need to describe serialization behaviour for every class that needs to be serialized. This is a direct consequence of the fact that C++ provides no reflection or introspection (the two main ways of achieving generic serialization algorithms).

Quote:Original post by drakostar
Why would you have any of that mixed in with your game world representation? Good OO practice and/or a proper multi-threaded game engine requires an independent model, from which the representations in the renderer, physics engine, etc. are derived.


Good OO practice and/or a proper multi-threaded game requires a model that is statically independent: model functionality may not explicitly access view functionality, and any interaction between them must be handled by controller objects.

However, must the controller objects necessarily interact with the model through polling? Is there any reason to forbid the Observer design pattern from being used? Listeners? Callbacks? The C# Event-and-Delegate pattern?
Quote:Original post by Drigovas
...[by the way, structs are pretty similar to classes in c++. Very, very similar...


Just wanted to clarify this a little. Classes and structs only have one difference: the members of a class have the default protection-label of private, whereas a struct has the default protection-label of public.

This topic is closed to new replies.

Advertisement