Loading game objects from file

Started by
7 comments, last by nickmerritt 20 years ago
Basicly I would like to know the best way to load/save objects to file. I have been trying to solve it for a while, and my current approch isn''t very nice. Basicly the problem is not reading from a file but what to do with it after. Basicly I can copy the whole file to memory or read it line by line but what do I do with it. How do I know whether it is a string, an int or any other format(custom types/classes) for that matter. Just really asking how you read objects in from file. Thanks, Nick Müsli Games www.musli.tk
Nick
Advertisement
First, you need to get elf food. Then, you put it in your computer. Then, you put out an ad for file elves, which do all of the tough work for you.

Alternatively, you do all the hard work yourself. This involves knowing exactly how your files are supposed to be laid out, so that you know that if there''s supposed to be an int here, read an int, and if there''s supposed to be a string

So, everything is written into the file and read out of it has to be in exactly the same order. The way you know what type of data you''re supposed to read at what point in the file is that you decide "OK, my files consist of an int followed by a double followed by a struct" (or whatever sets of variables make sense for what you''re doing), then you make sure your code always sticks to these rules, and reads and writes data of the exact same types, in the exact same order.

If you''re using C++ and fstreams, code for reading and writing the data in an object might look a little bit like this...

struct MyStruct{   // some data goes here....};class MyClass{   private:      int mInt;      double mDouble;      MyStruct mMyStruct;   public:      void ReadIt(istream &streamIn);      void WriteIt(ostream &streamOut);      // other methods for doing more interesting stuff with the class go here...};void MyClass::ReadIt(istream &streamIn){   streamIn.read(&mInt, sizeof(int));   streamIn.read(&mDouble, sizeof(double));   streamIn.read(&mMyStruct, sizeof(MyStruct));}void MyClass::WriteIt(ostream &streamOut){   streamOut.write(&mInt, sizeof(int));   streamOut. write(&mDouble, sizeof(double));   streamOut. write(&mMyStruct, sizeof(MyStruct));}
File formats is a fairly important topic, and one that''s very seldom actually covered in academia (because "everything''s XML" or "the object broker should take care of that" or whatever, I guess).

There are a few simple steps:

1) each object must know what data it needs to save/restore
2) you must have a mechanism for saving out object links, and reading them back in
3) you must have the actual I/O working

The first point can be solved with printf()/scanf(), operator<>, structs that you fwrite()/fread(), magic template members that serialize (using one of these methods) on demand, etc. I prefer structs/fwrite/fread, ''cuz I''m old skool :-)

Matching object links is best done (IMO) by traversing all objects, building a look-up table between "pointer value" and "linear ID", and saving out the ID with the object. Each object puts its ID first in the struct or description of itself. When you read the file in again you save the pointer for each object with the ID when you re-create the objects. Once you have created all objects, you traverse the graph again and let the objects pick out the appropriate pointer values based on ID (i e, the reverse of the initial table).

If you need the file format to transport between different architectures, or different versions of the software (where objects can change in size, etc), then you need to pay attention in step 1; you need to perhaps swap bytes, or be able to read an older version of the object and make up whatever information is missing.

Perhaps the most important part of writing file formats is to remember to put a magic number/string at the top of the file (so you can easily tell if the file is of the right kind), and a version number. You should pass the version number along to all object reader implementations, so that they know exactly what kind of data to expect for themselves.

Last, the actual I/O: it''s convenient to abstract I/O into a simple interface that just allows reading, writing, seeking, and asking how big the file is. That way, you can do it in memory, or to file, or to network, or whatever. Code all your file I/O to use this interface, rather than standard library functions. If you''re really l33t, you''ll come up with a system that lets objects live on disk until they''re needed, and save themselves back to disk when not needed anymore, thus saving memory.

Good luck!
enum Bool { True, False, FileNotFound };
CautionMan:
I was hoping for a better way because that is currently what I do. How would you take a line of input. Say
ntiles 12
and break that into a sting and an int?
Or should I even do that.

hplus0603: I''m not quite sure what you are saying. Basicly are you giving me a way to save and load objects that have refences/pointers to other objects. That is a problem that I think you solved however I''m still not actually sure what you are saying.

Anyways, thanks so far..

However how does an actual game save their objects.



Nick
Müsli Games
www.musli.tk
Nick
nick: it is done the way the two above posters described. It is called serialization. You need to add methods to your objects that can read/write the data that is to be saved to a stream for instance. But the above posts descibe it, and you can allways google for "serialization". Or have a look at codeproject i think they had some tutorial on it, not sure.
Shields up! Rrrrred alert!
an enguinity article discusses serialization.
3D Side-Scroller game demo Project-X2 "playable"Lashkar: A 3D Game & Simulation Project demo @ lashkar.berlios.de
Thanks, I''ll have a look. So basicly, a knew you made methodes for your objects that read write, but do you just make sure they know the exact type that they need. Ie: if they need an int, they read in a int, if they need a char they read in a char?
Anyways Thanks everyone,


Nick
Müsli Games
www.musli.tk
Nick
I know nothing practical about this stuff because I never bothered to study on it. Just read a dozen of tutorials on serialization on net. I think NebulaDevice1/2 has a complete system on it.

check this boost tut
http://www.rrsd.com/boost/libs/serialization/doc/tutorial.html

[edited by - DirectxXx on April 6, 2004 4:04:04 AM]
3D Side-Scroller game demo Project-X2 "playable"Lashkar: A 3D Game & Simulation Project demo @ lashkar.berlios.de
before i tried writing a parser, however a parser is too
much work so i do something like this
(note: i''m doing this all from memory so it may be slightly off)

#include <stdio.h> #include <iostream>class cSerialize // serialization class{   inline void read(FILE *pFile)   {      long filePos = ftell(pFile);       fread(this, filePos, sizeof(this), pFile);    }   inline void write(FILE *pFile)   {      long filePos = ftell(pFile);       fwrite(this, filePos, sizeof(this), pFile);    }};class Test : public cSerialize{   int var; };int main(void){   Test myTest;   myTest.var = 7;   FILE *pFile = fopen("newfile.txt","wb");   myTest.write(pFile);    fclose(pFile);    myTest.var = 2;   pFile = fopen("newfile.txt","rb");   myTest.read(pFile);    fclose(pFile);    std::cout << myTest.var << std::endl; // should cout 7   return 0;} 

This topic is closed to new replies.

Advertisement