PDA

View Full Version : Saving data



xGTx
21-02-2005, 06:39 AM
Hey everyone! Glad the sites back up...


Ive got a bit of a question... How would you guys go about saving data to a file (for say data for a Map file for your game)? My map file uses alot of dynamic arrays so you cant just save the type or anything. How i've gone about doing it is simply setting up a string and filled it with all the data i need, split up by dilimeters i can later split when i need to load, and just save that string's data. Is there a better way to do this? Maybe more professional and not so tacky.


Thanks!

JSoftware
21-02-2005, 08:13 AM
Use blockwrite and blockread to save the dynamic array into a binary file.
I don't remember whether blockread automatically resizes the array when you read a block?
Look it up at google and you'll find loads of examples

cairnswm
21-02-2005, 11:19 AM
I use a TStringList descendant that functions as a Database. I use the Name part of the string as a Table.Field.PK structure and the Value as the value of the field

So for example a user would be represented as
User.Name.1=William
User.Surname.1=Cairns
User.Location.1=South Africa

And it works well. For Maps (Mine are static arrays) I just use Text Files.

Crisp_N_Dry
21-02-2005, 12:58 PM
as JSoftware says, use BlockRead/BlockWrite. You will need to SetLength your array when loading as it will not do this automatically. Thing to do is to save the size of the array at the start of the file, when it comes to loading, load the array size value and use SetLength to set array to the right size. Use AssignFile to initialise the file and then use Reset and Rewrite commands. Reset loads an existing file (Use this on your loading routine). Rewrite creates or overwrites an exisiting file (Use this on your save routine).

Here's a quick example



Type
TTile = Record
ImageIndex: Integer;
Position: TPoint;
Blocked: Boolean;
end;

var
Map: Array Of TTile;

procedure SaveMap(Filename: String);
var
F: File;
X,Y: Integer;
L: Integer;
begin
AssignFile(F,Filename)
Rewrite(F,1);
//Write the map size to file
L:=Length(Map);
BlockWrite(F,L,SizeOf(Integer));
//Itterate through each tile and save it to a file
For X:=Low(Map) To High(Map) Do begin
BlockWrite(F,Map[X,Y],SizeOf(TTile);
end;
CloseFile(F);
end;

procedure LoadMap(Filename: String);
var
F: File;
X,Y: Integer;
begin
AssignFile(F,Filename)
Reset(F,1);
//Set map to correct size
BlockRead(F,L,SizeOf(Integer));
SetLength(Map,L);
//Itterate through each tile and load it from a file
For X:=Low(Map) To High(Map) Do begin
BlockRead(F,Map[X,Y],SizeOf(TTile);
end;
CloseFile(F);
end;

begin
SetLength(Map,1024);
SaveMap('Map.Dat');//or - LoadMap('Map.Dat') - whatever.
end;


These are pretty basic map load/save methods but they should work, bearing in mind I'm writing this from memory. A couple of things to remember is that you can NOT write a string to file using BlockWrite(F,MyString,SizeOf(MyString))
because in reality a String is just a pointer and this will simply write the pointer location to file which will change every time the program is run. For string you must itterate through each character and use BlockWrite to write each character in sequence. Don't forget to SetLength the string at the start though. In fact, writing a string to file is a lot like writing a map to file. Anyway, this is the best way I've found of doing things. Hope all this makes sense and if anyone wants to correct me on any of this then be my guest.



EDIT Had two loops in there beforehand, was using a 2 dimensional static array but realised you wanted it dynamic. Fixed the code now. Well spotted JSoftware.

JSoftware
21-02-2005, 01:10 PM
just to add to master Crisp_n_Dry's example then it can be done much shorter!
Type
TTile = Record
ImageIndex: Integer;
Position: TPoint;
Blocked: Boolean;

var
Map: Array Of TTile;

procedure SaveMap(Filename: String);
var
F: File;
X,Y: Integer;
L: Integer;
begin
AssignFile(F,Filename)
Rewrite(F,1);
//Write the map size to file
L:=Length(Map);
BlockWrite(F,L,SizeOf(Integer));
BlockWrite(F,Map[0],l*SizeOf(TTile);
CloseFile(F);
end;

procedure LoadMap(Filename: String);
var
F: File;
X,Y: Integer;
begin
AssignFile(F,Filename)
Reset(F,1);
BlockRead(F,L,SizeOf(Integer));
SetLength(Map,L);
BlockRead(F,Map[0],l*SizeOf(TTile);
CloseFile(F);
end;

begin
SetLength(Map,1024);
SaveMap('Map.Dat');//or - LoadMap('Map.Dat')
end;

as for the string saving and loading just define a new type like this:


type binarystring = string[1000]; //or what size you want


Well the example i made was only valid if you are using a one dimensional array. if you use multidimensional then you have to go with crisp_n_dry's example though it can still be shortened down to one for loop

Regards
Jeppe

xGTx
21-02-2005, 07:33 PM
Thanks guys

Lightning
25-02-2005, 04:27 PM
You could also use streams instead of BlockRead/BlockWrite as they are abstract, compatible with all stream types (file, memory, resource ...), they are also CrossPlatform and supported by FPC.
You can also subclass them and make custom streams for various data.

K4Z
25-02-2005, 04:57 PM
I prefer to use TFilestreams, when working with files. Gives you more control of the data, and works really well with dynamic arrays, and TMemoryStreams

bekuzofu
18-06-2005, 02:10 AM
how does the tstringlist work? is it a component? I'm new to delphi & dont have enough knowledge on strings.

JSoftware
18-06-2005, 06:37 PM
the tstringlist class is.. a class. it's a non vcl/lcl class, which means, no it's not a component: you have to initialize it as a variable. ex:

procedure tform.form1oncreate(sender: TOBject);
var stringlist: tstringlist;
begin
stringlist := tstringlist.create;
stringlist.add('Jeppe');
stringlist.add('is');
stringlist.add('pretty cool');
stringlist.savetofile('testfile.txt');
stringlist.free;
end;

this would output:

Jeppe
is
pretty cool

to testfile.txt in the same dir as the application is in. this data can be loaden in using the stringlist.loadfromfile(filename here); procedure you just have to remember to create the stringlist first. and nearly more important destroy it afterwards(we're afterall speaking gamedev on this site :wink: )

Happy coding

Sincerely,
Jeppe

EDIT: D'oh.. just saw the other thread...