• 01/15/01 03:25 PM
    Sign in to follow this  
    Followers 0

    Writing your own Load / Save routines

    General and Gameplay Programming

    Myopic Rhino
    This is my first article for GameDev.net so go easy on me. If you want to say thanks, correct something, or just flame, just mail me, all feedback is good feedback (no death threats please).

    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:
    1. Create file and verify that it's valid
    2. Write signature to file
    3. Write important file description to file
    4. Write all variables necessary
    5. Close file
    Ok, now let's analyze each of these.

    [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
    }
    Now that was easy, let's check the next one.

    [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);
    For you C genius out there I think I don't have to explain the fwrite routine, but I'll do it for the sake of the beginners out there. So, it is as follows, we supply a pointer to the string as first parameter (SIGNATURE points a pointer to SIGNATURE[0], now is the weird part, we must supply the size of the type of variable we are trying to write to the file, in this case char, and then, how big is the string, in this case 4 bytes (LSD + "\n" for end line). Now we just supply the pointer to the file stream and off we go.

    [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];
    In this piece of code we created two arrays, one of sPlayer and another of sEnemy, so we know we have two players and 20 enemies, this is what we will write to the file.

    fwrite (&PLAYERS, sizeof(int), 1, SaveFile);
    fwrite (&ENEMIES, sizeof(int), 1, SaveFile);
    You already know how fwrite works so no more explaining to do. Just want to remember when passing single variables to fwrite you need to pass the address of them.

    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);
    Again we need to give fwrite the size of the variables and all it is done.

    [size="3"]5. Close file

    This is the hardest part you need to close the file.

    fclose (SaveFile);
    It was hard right?


    [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.
    1. Open file and verify if valid file
    2. Read header
    3. Read all variables necessary
    4. Close file
    And another type, step-by-step.

    [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
    }
    Just like for saving, but instead of writing mode, we open it in reading mode.

    [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);
    And that's it, you have yourself the header loaded.

    [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);
    We use the variables we loaded (lowercase) to know how many were saved.

    [size="3"]4. Close file

    Again

    fclose (LoadFile);
    And that's the end of our Load routine.


    [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
    0


    Sign in to follow this  
    Followers 0


    User Feedback

    Create an account or sign in to leave a review

    You need to be a member in order to leave a review

    Create an account

    Sign up for a new account in our community. It's easy!


    Register a new account

    Sign in

    Already have an account? Sign in here.


    Sign In Now

    There are no reviews to display.