I'm here to (try) to explain how to make a Load/Save routine. I'll use non-platform-specific C so people can use the code in DOS/Windows/Linux/whatever supports ANSI C. (I was thinking of also doing a C++ version of the code, but most people prefer C for pure write and read functions. If you need the code for C++, mail me and I'll send you the C++ version.)
[size="5"]Saving the file
I'll try to explain the best way I can how to do a save routine in 5 easy steps. The main loop goes like this:
- Create file and verify that it's valid
- Write signature to file
- Write important file description to file
- Write all variables necessary
- Close file
[size="3"]1. Create file and verify that it's valid
This is probably the easiest thing to do, you will just have to create a file and check if it was created correctly.
#include
// Game stuff here
FILE *SaveFile;
char FileName[] = "MyGame.svg";
SaveFile = fopen (FileName, "wb"); // opens file for writing and in binary mode
if (SaveFile == NULL)
{
// Error while creating file
}
[size="3"]2. Write signature to file
I must be honest with you, this is not necessary to your save game file, but is a help for loading, I'll explain why later, when I cover the Load routine. So to write a signature file to the game you just have to add a string to your file.
const char SIGNATURE[] = "LSD"; // for Load / Save Demo
fwrite (SIGNATURE, sizeof(const char), sizeof(SIGNATURE), SaveFile);
[size="3"]3. Write important file description
Now for the hard part starts, for this part we will imagine we are making a invaders clone, so we will need some variables to old score, life, etc. We will use a struct so it can be easier to write and read from.
const int ENEMIES = 20;
const int PLAYERS = 2;
typedef struct
{
char PlayerName [11];
unsigned char Lives;
int xPosition;
int yPosition;
int Score;
int BulletsLeft;
int Level;
} sPlayer;
typedef struct
{
unsigned char Alive;
int xPosition;
int yPosition;
int Speed;
} sEnemy;
sEnemy Enemies[ENEMIES];
sPlayer Players[PLAYERS];
fwrite (&PLAYERS, sizeof(int), 1, SaveFile);
fwrite (&ENEMIES, sizeof(int), 1, SaveFile);
After completing this step, we can say we have written the save file header !
[size="3"]4. Write all necessary variables
Now for the real, real hard part (ok, not so hard but I like to glorify myself), we shall write all the data to the file. We will use fwrite so we can write the entire info of players and enemies in two simple calls.
fwrite (Players, sizeof (sPlayer), PLAYERS, SaveFile);
fwrite (Enemies, sizeof (sEnemy), ENEMIES, SaveFile);
[size="3"]5. Close file
This is the hardest part you need to close the file.
fclose (SaveFile);
[size="5"]Loading the file
If you got all the stuff this far, then this will be a singe. Loading a file is like saving it basically, let's see the steps we need.
- Open file and verify if valid file
- Read header
- Read all variables necessary
- Close file
[size="3"]1. Open file and verify if valid file
We will open the file and see if it exists.
FILE *LoadFile;
char FileName[] = "MyGame.svg";
LoadFile = fopen (FileName, "rb"); // opens file for reading and in binary mode
if (LoadFile == NULL)
{
// Error while creating file
}
[size="3"]2. Read header
We only have in our header three variables, below is a table explaining the all file. Name Size Description SIGNATURE 4 bytes Signature file PLAYERS OS dependet (int) Number of players ENEMIES OS dependet (int) Number of enemies Players PLAYERS * sizeof (sPlayer) Players information Enemies Enemies * sizeof (sEnemy) Enemies information
Now we load the header info into some variables.
char SIGNATURE[4];
int PLAYERS;
int ENEMIES;
fread (signature, sizeof (char), 4, LoadFile);
// you should check the signature to see if is equal to LSD
fread (&players, sizeof(int), 1, SaveFile);
fread (&enemies, sizeof(int), 1, SaveFile);
[size="3"] 3. Read all variables necessary
Now this is just like the save part (again).
fread (Players, sizeof (sPlayer), players, SaveFile);
fread (Enemies, sizeof (sEnemy), enemies, SaveFile);
[size="3"]4. Close file
Again
fclose (LoadFile);
[size="5"]Further Sugestions and Remarks
This part is the cooler one in my opinion, I'll give you suggestions I think it should be cool to implement in the Load / Save Demo.
[size="3"]Encryption
If you don't want that the more experienced user to pick up your saved file and edit it so he has a 100000000000 * 10 ^ 99 score then you should add encryption. It's cool and it protects you from players that want to be number one, even if they can't play the game.
[size="3"]Compression
In this article we used very small structs and variables, but imagine you have 100 floating values, about 1000 structs for objects and more information you want to save, this would create a very big, big file (I still remember Championship Manager 2 where I needed 16 Megabytes of free space just to save). To compensate this, one idea is to compress the saved file
[size="3"]Multiple files
This is just to simplify loading and reading routines. It's a good idea to store all player variables in one file, world variables in another, objects in another and so on.
[size="3"]Filenames
Allow the user to choose the filename he wants to save to, this is an obvious subject but since in this demo I made it hard coded, you could forget right?
Now for the regards (I hate this part).
[size="3"]Restoring things
Remember, after loading the file, to load all images needed, maps, and stuff, because you will probably need to load all that stuff again (it should very bad if you loaded a game in level 6 and the artwork would still be from level 1).
[size="3"]Make a header
Always make a header for your files, so you can load the header first, and then see what you will load (you don't want to pass by the end of file do you?).
Enough is enough, conclusion !
Ok, it is time to say goodbye, but... "I'll be back". Just play a little with the source code, experiment, and if you discover something cool, send it to me.
Oh, not to forget, if you have ideas of articles you would like me to write, send your suggestions. Heck, send me even if you don't have suggestions, even if it is only to say you learned something or not, I WANT feedback!
Bruno Sousa (Akura)
[email="Akura@Logicmatters.cjb.net"]Akura@Logicmatters.cjb.net[/email]
http://logicmatters.cjb.net