Game Development Community

dev|Pro Game Development Curriculum

Saving and Loading with Torque

by Pat Wilson · 11/08/2004 (8:27 am) · 39 comments

Download Code File

A lot of people ask if Torque can save and load games. The answer is yes, and no. No you can't just say "Torque, save my game!" any more than you can say, "Torque, read my mind and make this awesome MMORPG that I'm sure NOBODY has thought of before." You need to tell Torque what data you want to save, and in what order you want to save it. The code is attached, if you want to play with it, just compile it in to Torque and it will work.

First, the object
class LoadSaveObject : public SimObject
{
   typedef SimObject Parent;

protected:
   S32 mSomeS32;
   StringTableEntry mSomeString;
   F32 mSomeF32;

public:
   LoadSaveObject() : mSomeS32(0), mSomeString( "" ), mSomeF32( 0.f ) {};
   static void initPersistFields();

   bool saveToFile( const char *filename ) const;
   bool loadFromFile( const char *filename );

   DECLARE_CONOBJECT(LoadSaveObject);
};

Note that there are some data members in there, we will be saving that data, in the functions 'saveToFile' and 'loadFromFile'.

Without further delay, the save function
bool LoadSaveObject::saveToFile( const char *filename ) const
{
   char fname[1024];
   if( filename )
      if( Con::expandScriptFilename( fname, sizeof( fname ), filename ) )
         filename = fname;

   FileStream fs;
   if( !fs.open( filename, FileStream::Write ) )
   {
      Con::errorf( "LoadSaveObject: Could not open '%s' for writing.", filename );
      return false;
   }

   fs.write( mSomeS32 );
   fs.writeString( mSomeString, dStrlen( mSomeString ) );
   fs.write( mSomeF32 );

   fs.close();

   return true;
}

Note the order in which we wrote things in to the file, we need to read them out in exactly the same order in the read function.
bool LoadSaveObject::loadFromFile( const char *filename )
{
   char fname[1024];

   if( filename )
      if( Con::expandScriptFilename( fname, sizeof( fname ), filename ) )
         filename = fname;

   FileStream fs;
   if( !fs.open( filename, FileStream::Read ) )
   {
      Con::errorf( "LoadSaveObject: Could not open '%s' for reading.", filename );
      return false;
   }

   fs.read( &mSomeS32 );

   char buffer[256];
   fs.readString( buffer );
   mSomeString = StringTable->insert( buffer );

   fs.read( &mSomeF32 );

   fs.close();

   return true;
}

You now have a object you can mess with from script that will save and load. Here is a little script you can use to test it out.
$foo = new LoadSaveObject();
$foo.someS32 = -42;
$foo.someString = "tEsTING caSE SEnSITIvE STRingS!";
$foo.someF32 = 3.14159;
$foo.saveToFile( "~/saved.foo" );

$bar = new LoadSaveObject();
$bar.loadFromFile( "~/saved.foo" );
echo( $bar.someS32 );
echo( $bar.someString );
echo( $bar.someF32 );

Now go forth and make something!
Page«First 1 2 Next»
#21
07/06/2005 (11:24 pm)
Looks good! I'll definately be able to use this..... but it'd be nice if it could encrypt it. Guess it can't do it all.
#22
07/28/2005 (6:52 am)
There are tons of ways to encrypt an external file, search through the resources, I bet there is one, then just save your file, call the encrption and encypt it, then when its loaded, decrypt it load it in memory and encrypt it back again.
#23
08/12/2005 (6:01 am)
perfect resource :)

If anyone is monitoring this... Is there a simple way to save and load a matrix ? I want t save out my Player transform, and I'd rather not have to rip it apart to save and rebuild it when I load.

Also, I am trying to save out my bots. I am going to do a radius search to find them all, but there is no guarantee as to how many there will be. Can you give me an exapmle of how to save a variable number of variables :)
#24
09/30/2005 (7:12 am)
As far as your matrix goes you might be better off ripping it apart and then loading it back on runtime, it may take a little longer to load but I feel this would be much cleaner.

I am not sure how a radius seach returns databack to you, most likely in an array I would use a for or a while loop to save the data. This isnt to hard and is something good to know as a coder.

Cycling through arrays is pretty much a need to know thing, so give it a whirl and if you dont get it email me :)
#25
09/30/2005 (9:23 am)
Isaac - I know ohw to cycle through an array... and I ended up just ripping open the matricies and saving them that way.

Thank you for your reply.
#26
12/07/2005 (3:44 pm)
maybe this is a stupid question - is there not some way to load and save using just script? we have to add resources to the engine just to do basic loading and saving of data?

seems so basic, but if you want to do this simple thing you've got to mess with a c++ compiler. kinds of defeats what some folks are using torque for, to avoid all the c++. I'm not saying Blitz is the greatest (i'm switching to torque from it), but at least it gives you the commands to do basic file operations. ?
#27
12/07/2005 (3:53 pm)
you can save out text files from Torque Script very easily
#28
03/16/2006 (5:52 am)
hi boy...Ehm....What use this reaource? i put this file in?------- help please----- =) thanks
#29
03/22/2006 (2:44 pm)
nice :)
#30
06/24/2006 (4:54 pm)
I've looked around and can't find out how to actually get torque to use the .cpp file, I even found the MakeFile.

I understand what the code does and how it does it, but where do I put the file and how do I tell Torque to register it so that I can use this code?:

$foo = new LoadSaveObject();
$foo.someS32 = -42;
$foo.someString = "tEsTING caSE SEnSITIvE STRingS!";
$foo.someF32 = 3.14159;
$foo.saveToFile( "~/saved.foo" );

$bar = new LoadSaveObject();
$bar.loadFromFile( "~/saved.foo" );
echo( $bar.someS32 );
echo( $bar.someString );
echo( $bar.someF32 );


Thanks for the resource =) Once I figure out how this part works, it'll be really useful =)
#31
07/30/2006 (2:37 pm)
Jyan,

Add the .cpp file to your engine :) you could place it in the \engine\game folder, and then add it to your Solution.

Then rebuild your Torque Demo (or Game Executable)

Then edit the .cs file you want - depending on where you want to Load/Save something.

If you wanted to make a save game point, you would simply add the whole
$foo = new LoadSaveObject();
$foo.someS32 = -42;
$foo.someString = "tEsTING caSE SEnSITIvE STRingS!";
$foo.someF32 = 3.14159;
$foo.saveToFile( "~/saved.foo" );

to the ::OnCollision function
of that Object



Hope that explains it a little better.
-Rob Janes
#32
08/01/2006 (1:37 pm)
Ok thanks a lot, I'll try that =)
#33
09/30/2006 (10:06 pm)
Great resource. Definitely gets you on the right track if you want to write out and read in whole blocks of data.

For writing to basic text files in a much more simple manner, check out this link:
http://tdn.garagegames.com/wiki/TorqueScript_FileObject

If talks about using the FileObject in script as opposed to utilizing customized code in C++:

%file = new FileObject();
%file.OpenForWrite("starter.fps/test.txt");
%file.writeline("This is the test file.");

%file = new FileObject();
%file.OpenForRead("starter.fps/test.txt");
%line = %file.readline();


I prefer the C++ method because it is cleaner and allows for the possibility of encrypting the data, but if you want something simple then the FileObject methods should do it for you.
#34
11/09/2006 (11:24 pm)
hi there
i am a newbie thus please do not mind if i ask something not upto the level
i was going through the resource and found that it is useful if used
but the problem is it does not specify as to where in the engine code does this cpp file has to be put in and then do i have to modify aby of the script files to use it and if so which are the files whom i have to modify and what modifications are required
and also will it create an icon of 'save' on the gui ?
or how do i save the game when i try to use it
if anybody who knows please tell me
thnaking you
#35
11/10/2006 (4:53 pm)
Hi Ryan ;)

You can add the .cpp file anywhere inside your game folders you want. Just make sure you include it into your project file before you compile it and always try to put those files inside folders that make sense.

You can use it by calling the functions: "saveToFile" and "loadFromFile" to save and load respectively.

This code won't make a save button on your gui. You will have to create a button on there somewhere and tell it to use the "saveToFile" function if you want to use this that way.

Sorry if I'm a little off, it's been a while since I've used this and I'm using something different now. Hope this still helps though Ryan!

edit:
Make sure you add code like this to a script or that button though:

$foo = new LoadSaveObject();
$foo.someS32 = -42;
$foo.someString = "tEsTING caSE SEnSITIvE STRingS!";
$foo.someF32 = 3.14159;
$foo.saveToFile( "~/saved.foo" );

$bar = new LoadSaveObject();
$bar.loadFromFile( "~/saved.foo" );
echo( $bar.someS32 );
echo( $bar.someString );
echo( $bar.someF32 );
#36
08/08/2008 (8:24 am)
Great resource man...
#37
06/15/2009 (1:21 am)
Excellent, thanks for the example. I'll eventually be working this into an entire quick-save system, which shouldn't require too much work. You need to implement a save/load method for each type of game object, writing and reading the required data, then call these methods on all the objects in the level you want to save, to dump their data into a file. The file format is similar to the mission file - you declare a bunch of new objects and set their properties according to the info in the file. To load a saved game, you just exec the savegame file, and it creates all the objects you need.
#38
10/03/2009 (4:37 pm)
@Daniel, sounds very good system, do you plan launch these as resource?
#39
12/13/2009 (3:36 am)
EDITED: This failed to compile for me and I had problems when using TGEA. So just to help out anyone who has TGEA and wants to try out this resource here is how you do it. Place the included cpp file in your projects folder anywhere. (Note that it's generally best to place it somewhere it makes sense.)
Next open your compiler and add the cpp file to your solution. Next we have to make some changes. I'd like to thank Scooby Brown on helping me with the changes.
Step 1: Change the line that says
#include "core/fileStream.h"
to
#include "core/stream/filestream.h"
Step 2: Change the following
if( !fs.open( filename, FileStream::Write ) )
to
if( !fs.open( filename, Torque::FS::File::Write ) )
and do the same to the line
if( !fs.open( filename, FileStream::Read ) )
to
if( !fs.open( filename, Torque::FS::File::Read ) )

That should be it.
Page«First 1 2 Next»