Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

what is the most used method or algorithm for saving game state (profiles), databases text files how there encryption goes and things related.

I have seen Caesar IV used mySQL.

any suggestions.

share|improve this question
add comment

5 Answers

up vote 20 down vote accepted

I'm pretty sure it is most often done in a proprietary (binary) format, just writing each variable from whatever game state struct you use into a file, or reading that file back into an instance of the struct. In C++ for example you can treat an object like an array of bytes and just fwrite() it into a file, or fread() from the file and cast it back into its object form.

If you are using Java or another language you can opt to use serialization to make the task really easy. The Java explanation is at the bottom of this answer; other languages (higher-level than C++) surely have their own serialization libraries or built-in functions as well, which you should opt to use. No matter how inefficient the serialization routine might be, hard drive space nowadays is cheap, especially when the game state shouldn't be very large at all, and it prevents you from writing and maintaining your own serialization routines.

You should absolutely not use MySQL (just read the first sentence of this review). If you really need a relational database for some reason, use SQLite; it is a lightweight database system and exists in a single database file. But for most games, relational databases are not the way to go, and companies which try to use them usually end up using them as a key-value lookup table rather than a true relational database.

Any sort of encryption of local disk files is only obfuscation; any hacker will just sniff the data right after your program decrypts it. I'm personally against that sort of thing, ESPECIALLY with one-player games. My view is that the owners of the game (paying customers, mind you) should be allowed to hack at the game if they want to. In some cases it can create a greater sense of community, and "mods" can be developed for your game which drive more customers to you. The most recent example that comes to mind is the Portal in Minecraft mod that was recently released. It's published in gamer news sites all over the internet, and you can bet it drove up sales of Minecraft.


If for some reason you are actually crazy enough to be using Java for game development like I am, here's a quick explanation of serialization in Java:

Keep all of your game state data in one class, make the class serializable by implementing Serializable, use the transient keyword if you mix special instantiated variables into the class (transient objects are not serialized), and simply use ObjectOutputStream to write to file and ObjectInputStream to read from file. That's it.

share|improve this answer
1  
Hehe, The Witcher did not encrypt their data. Very easy to open up the save game file in a hex editor, mess with it a bit and get all the naked chick cards... oh god, I am so sorry! –  anthony-arnold Aug 11 '10 at 23:47
    
I've used .NET binary serialization for saving games, and C# is perhaps a slightly more reasonable platform than Java on which to develop games. I like how it automatically saves a whole object graph automatically. This used to be so much more difficult. Of course now there's the challenge of excluding unnecessary pieces like the textures, but that's not a big deal to accomplish. –  BlueMonkMN Aug 12 '10 at 12:54
    
I don't disagree that C# is slightly more popular than Java to develop games. More reasonable implies some subjectivity, and as a developer of both XNA and Java, I prefer Java. Feel free to list instructions on serialization in C# too if you'd like, I've never done it but I can edit it into my answer. Java's serialization does save the whole object graph and the 'transient' keyword on variables excludes unnecessary pieces like textures; any non-transient members must be Serializable or you can write a custom writeObject method to get around that. –  Ricket Aug 12 '10 at 13:15
    
Python's pickle will save an entire object graph for you as well and is drop-dead easy to use. When it comes time to deserialize you are handed back fully hydrated objects, easy as pie: docs.python.org/library/pickle.html –  D. Hayes Aug 12 '10 at 19:58
    
When using the built-in binary formatter, excluding certain fields from serialization in C#/.NET is as simple as adorning them with the [NonSerialized] attribute. What's easy to overlook, however, is that compiler-generated events (i.e. any event without custom add/remove operators) create a backing field to store their subscribers. Thus, it's easy to accidentally (and unknowingly) include event handlers in a serialized object graph. To get around this, you need to add the NonSerialized attribute to the event declaration, but you need to add the "field:" qualifier: [field: NonSerialized] –  Mike Strobel Aug 20 '10 at 18:33
show 3 more comments

If you are writing your own code, say in C++, you can use binary files. Binary files give you a form of encryption through obfuscation. But as documented all over the internets, that is a very weak form of security.

OR, you can use something like RapidXML if you want a human readable solution.

If you are usuing some kind of framework, look into it's file support functions. HTH

share|improve this answer
add comment

Most games I've seen just use hand-written code to read/write from binary files. Often, the on disc format will be an exact replica of the memory layout of an object so loading is just:

  1. Read file into memory.
  2. Cast pointer to buffer to object type.

It's fast, but it's a chore to maintain, platform-specific, and inflexible.

Lately, I've seen a couple of games use SQLite. People I've talked to seem to like it.

share|improve this answer
add comment

Serialization is mentioned in some of the other answers, and I agree that is a reasonable solution. One way it fails though is in versioning.

Say you release your game and people play it and create some save games. Then in a later patch you want to fix a bug or add some features. If you use a simple binary serialization method and you add a member to your classes your serialization may not be compatible with the old save games when the customers install your patch.

So whatever approach you use, make sure you think of this issue before you release the game the first time! Customers will not be happy if they have to start over after applying a patch.

One way to avoid this is to have each basic data type implement Save(version) and Load(version) methods that are smart enough to know what data to save and load for each version of the game. That way you can support backward compatibility of your save games and fail gracefully if a user tries to load a save game from a newer version of the game than they are running.

share|improve this answer
1  
As a quick note: implementing "save" and "load" functions for each version of the game quickly turns into a maintenance nightmare. I've found a better solution is to embed a version number, write "save/load" functions for the current version of the game, and write a "conversion" function from the most recent non-current version to the current version. Then just keep all your conversion functions around. Trying to load a ten-version-old game would run ten conversion functions in series, then the native "load the current game version" function. –  ZorbaTHut Aug 13 '10 at 2:40
    
Much easier to maintain long-term - keeping a series of "load every previous game file" functions around quickly turns into a polynomial-time operation. –  ZorbaTHut Aug 13 '10 at 2:41
    
In games I've worked on it's not that complex -- rather than keeping multiple copies of the load/save methods the one single method uses the version number to determine which bytes to read and write. This is made even easier if you don't just write structures, but implement loading and saving as operations at the primitive data type level (e.g. ReadByte/ReadFload/etc). Then if you add a new member you can do something like if(version>10) { someNewByte = ReadByte(); } Implementing it this way makes supporting different endian platforms easier as well. –  kevin42 Aug 13 '10 at 11:49
    
Another way to avoid improve versioning support is to avoid having your objects' serialization/deserialization methods write/read individual values directly from a stream. Instead, objects could write their owned data into a property bag using key/value pairs, and then write the bag out to the stream. During deserialization, objects could read values from the bag by name. But instead of having specific version number checks like kevin42 suggested, you could just have rules for how to handle missing values (i.e. use a standard default value when the required value isn't in the bag). –  Mike Strobel Aug 20 '10 at 21:32
add comment

If you can use the same format that you use to store your levels in, it is a bonus.

For example, a game like Peggle might have an initial board layout, number of balls, current score (0 for the initial board), etc. Then a saved game can use exactly the same format.

If you use the same format then the save game and the level load can share code making your job easier!

For a game with really big map files, the save game can include the map file by reference. The initial level files might do the same thing, even, which makes coming back to that map easier too if for some reason the story has the character come back to the same place, except some of the NPCs are dead and there's dead bodies lying all over.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.