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.

I am coding my final for a Video game Programming course, and I want to know how to create a save file for my game, so that a user can play, and then come back later. Any idea how this is done, every thing I have done before has been single run programs.

share|improve this question
    
possible duplicate of How to create a game save file format in c++ using STL –  Ali.S Mar 21 '12 at 22:21
7  
@TuckerMorgan you might consider accepting any answer. –  kaoD Mar 21 '12 at 23:15
1  
@Shvelo While you could do that, it seems like it would add a lot of complexity that isn't necessarily needed. –  Nate Mar 22 '12 at 19:30
8  
I weep for the future of our industry, that one can reach the final for a programming course without having learned how to write files. –  Trevor Powell Mar 22 '12 at 23:31
1  
@TrevorPowell Well this is an intro to c++ and i am way a head of my class, i started on my final because my teacher has nothing else i can do. That i have not already done –  Tucker Morgan Mar 25 '12 at 2:07

6 Answers 6

You need use serialization to save your variables in memory to your hard drive. There are many types of serialization, in .NET XML is a common format, though there are binary and JSON serializers available. I'm not much of a C++ programmer, but a quick search turned up a few examples on serialization in C++:

The variables you will be interested in are going to probably be related to game state. For example, you will probably want to know this type of information

  1. The player was playing level 3
  2. The player was at X, Y world coordinates
  3. The player has three items in his backpack
    1. Weapon
    2. Armor
    3. Food

You wont really care what textures are being used (unless your player can change their appearance, that's a special case), because they are usually the same. You need to focus on saving important gamestate data.

When you start your game, you start as normal for a "new" game (this loads your textures, models, etc) but at appropriate time you load the values from your save file back into the game state object replacing the "default" new game state. Then you allow the player to resume playing.

I've greatly simplified it here, but you should get the general idea. If you have a more specific question ask a new question here and we can try to help you with it.

share|improve this answer
    
I understand what i need to save, but what i would like to know what is the exact way, do you save it to a .txt file in the project, those modified variables, or some other way –  Tucker Morgan Mar 21 '12 at 18:27
    
Yes, if your game is simple, a text file might be sufficient; you need to keep in mind that anyone can edit a text file and thus make their own save games... –  Nate Mar 21 '12 at 18:32
    
Text file saves aren't just for simple games. Paradox used a structured text format for save files for all the games they created using the same engine as the flagship Europa Universalis engine. Especially late game, these files could be enormous. –  Dan Neely Mar 21 '12 at 21:01
1  
@DanNeely A fair point, no reason you cannot use a text format to store lots of complicated data, but generally speaking, when your data is that complicated, the benefits of another format (binary, xml, etc) become more pronounced. –  Nate Mar 21 '12 at 21:05
1  
@NateBross Agreed. The Paradox games were very mod friendly and used a similar (identical?) format for scenario data. Storing most of their data as text meant they didn't need to invest in scenario editor tools for public use. –  Dan Neely Mar 21 '12 at 21:18

Typically this is specific to your game. I'm sure you've learned about writing to and reading from files in your classes so far. The basic idea is:

  1. When exiting the game, write the values you want to save to a file.
  2. When loading the game, check to see if a save file exists, if it does, load the read the values in to your program. If the file does not exist, continue like you do now and set the values to their starting/default values.

What you write is up to you, it depends on your game. One way of writing is to write out the variables you want in a specific order as a byte stream. Then when loading, read them in to your program in the same order.

For example (in quick pseudo code):

SaveGame(FileInput file) {
    file.writeInt(playerLevel);
    file.writeInt(playerHealth);
    file.writeInt(gameProgress);
}

LoadGame(FileInput file) {
    if(file.exists()) {
        playerLevel= file.readInt();
        playerHealth = file.readInt();
        gameProgress = file.readInt();
    } else {
        playerLevel = 1;
        playerHealth = 100;
        gameProgress = 0;
    }
}
share|improve this answer
1  
This method is nice and small, though I'd recommend putting in some simple tags for chunks of data. That way if later on you need to change something that's normally in the middle of the file, you can do so and the only "conversion from old" you have to do is within that one block. It's not as important for a one off assignment, but if you continue work after people start getting save files it's a bit of a nightmare just using straight bytes with position being the only identifier. –  Lunin Mar 21 '12 at 19:14
1  
Yep, this does not generate future-proof save files. It also doesn't work for data that has variable byte sizes like strings. The latter is easy to fix by first writing the size of the data that's about to be written, then using that when loading to read the correct number of bytes. –  Byte56 Mar 21 '12 at 19:31

There are probably a large number of ways to do this, but the simplest that I always found and have used both personally and professionally is to make a structure that contains all of the values I want saved.

struct SaveGameData
{
    int              characterLevel; // Any straight up values from the player
    int              inventoryCount; // Number of items the player has on them or stored or what not
    int[STAT_COUNT]  statistics;     // This is usually a constant size (I am tracking X number of stats)
    // etc
}

struct Item
{
    int itemTypeId;
    int Durability; // also used as a 'uses' count for potions and the like
    int strength;   // damage of a weapon, protection of armor, effectiveness of a potion
    // etc
}

I then just fwrite/fread the data to and from a file using the basic File IO values. The inventoryCount is the number of Item structures that are saved after the main SaveGameData structure in the file so I know how many of those to read after fetching that data. The key here is that when I want to save something new, unless its a list of items or the like, all I have ever have to do is add a value to the structure some where. If its a list of items then I will have to add a read pass like I have already implied for the Item objects, a counter in the main header and then the entries.

This does have the downside of making different versions of a save file incompatible with each other with out special handling (even if it is just default values for each entry in the main structure). But overall this makes the system easy to extend just by adding in a new data value and putting a value into it when needed.

Again, quite a few ways to do this and this might lead more towards C than C++, but it has gotten the job done!

share|improve this answer
1  
It's also worth noting that this is not platform-independent, won't work for C++ strings, or for objects referred to via references or pointers, or any objects containing any of the above! –  Kylotan Mar 21 '12 at 20:31
    
Why isnt this platform independent? It worked fine on the PC, PS* systems and the 360.. fwrite(pToDataBuffer, sizeof(datatype), countOfElements, pToFile); works for all of those objects assuming you can get a pointer to their data, and the size of the object and then the number of them you want to write.. and read matches that.. –  James Mar 21 '12 at 21:42
    
It is platform-independent, there's just no guarantee that files saved on one platform can be loaded on another one. Which is rather irrelevant for e.g. game data saving. The pointer-to-data-and-size-memcpy stuff can obviously be a bit awkward, but it works. –  leftaroundabout Mar 22 '12 at 0:58
2  
Actually there's no guarantee that it'll keep working for you forever - what happens if you release a new version that's built with a new compiler or even new compilation options that changes the struct padding? I would strongly, strongly discommend the use of raw-struct fwrite() for this reason alone (I am speaking from experience on this one, incidentally). –  fluffy Mar 22 '12 at 4:15
    
I'd still suppose that this solution is sufficient for the project scope. Chances are that any serialization library weighs more than the entire game. Also, correct me if I'm wrong but using POD structs in C++ will guarantee that the memory layout of an instance is as specified in the definition. Kylotan's criticism still stands, though. –  Koarl Mar 22 '12 at 9:10

First you need to decide what data needs to be saved. For instance, this could be the location of the character, his score, and the number of coins. Of course, your game will likely be much more complex, and so you will need to save additional data such as the level number and enemy list.

Next, write code to save this to a file (use ofstream). A relatively simple format you can use is as follows:

x y score coins

And so the file would look like:

14 96 4200 100

Which would mean he was at position (14, 96) with a score of 4200 and 100 coins.

You also need to write code to load this file (use ifstream).


Saving enemies can be done by including their position in the file. We can use this format:

number_of_enemies x1 y1 x2 y2 ...

First the number_of_enemies is read and then each position is read with a simple loop.

share|improve this answer

One addition/suggestion would to add a level of encryption to your serialization so users cannot text edit their values to "9999999999999999999". One good reason to do this would be to prevent integer overflows (for example).

share|improve this answer

I think your best bet is boost::serialization because is easy to propagate down in your hierarchy. You only need to call the top object's save/load function and all your classes are easily created.

See: http://www.boost.org/doc/libs/1_49_0/libs/serialization/doc/index.html

share|improve this answer

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.