• Main Page
  • Related Pages
  • Classes
  • Files
  • File List
  • File Members

save.dxt

00001 /*
00002    $Id: save.dxt,v 1.1 2001/10/15 15:00:06 gnurou Exp $
00003 
00004    Copyright (C) 2001   Alexandre Courbot
00005    Part of the Adonthell Project http://adonthell.linuxgames.com
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License.
00009    This program is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY.
00011 
00012    See the COPYING file for more details.
00013 */
00014 
00015 /*! 
00016 
00017 \page page6 Saving/Loading
00018 
00019 \section objdatobjst Object data and object state
00020 
00021 This is another important part of the %game engine. Quite a few %objects should
00022 be loadable and saveable, but there is a difference between two things
00023 that may look like one: an %object's %data itself and an %object's state.
00024 
00025 But there is a significant difference. Data is all the information that stays
00026 the same during an %object's lifetime. As a consequence, %data remains persistent
00027 over the whole %game. An %object's state is the information that changes while the
00028 %game progresses.
00029 
00030 For example, when loading a map, all the actual graphics are persistant %data.
00031 OTOH, player and NPC's are certainly no longer at their initial position, so
00032 this information belongs to the map's state.
00033 
00034 Let's see precisely how it works with a simple %animation class:
00035 
00036 \verbatim
00037 class animation
00038 {
00039 public:
00040     // Constructor / Destructor.
00041     animation ();
00042     ~animation ();
00043 
00044     .....
00045 
00046     // Saving / Loading methods.
00047     void get (FILE * in);
00048     void put (FILE * out);
00049 
00050     // State saving / loading methods.
00051     void get_state (FILE * in);
00052     void put_state (FILE * out);
00053 
00054 private:
00055     vector <image> frames;
00056 
00057     u_int32 currentframe;
00058 }
00059 \endverbatim
00060 
00061 The difference between the %object %data and the %object state is quite obvious here: the
00062 \e frames vector is an array containing the raw %images - they won't change during 
00063 gameplay, so they are considered as the %object \e %data, while the \e currentframe
00064 member will change during the %game, and actually when we load a %game we would like
00065 it to have the same value than when we saved it. That's why \e get and \e put will
00066 save the \e frames vector (and maybe put \e currentframe to 0 for \e get, to make sure
00067 the %object is in a stable state), and \e get_state and \e put_state will save/load the 
00068 currentframe member. That way, when you load a %game, you can simply get the %object state
00069 from the save file, while the %object itself will be loaded from the %data directory.
00070 
00071 \section convsave Conventions for saving/loading methods
00072 To reduce the amount of space needed for the %game, loading/saving methods use the igzstream
00073 and ogzstream classes for disk access. See their own documentation for more details.
00074 
00075 The saving methods should be constant - that is, they doesn't change the state of the %object
00076 itself. The loading methods should always bring the %object into a stable state once they 
00077 return (think of what would happen if you load an %animation and the \e currenframe member
00078 remains with a value superior to the actual number of %images in this %animation). The 
00079 declaration conventions are the following (you can use this template declaration for your
00080 own classes, as it also shows you the proper way to document your code with sections):
00081 
00082 \verbatim
00083 class myclass
00084 {
00085 public:
00086 
00087 .....
00088 
00089     /**
00090      * @name Loading/Saving methods
00091      *
00092      */
00093     //@{
00094         
00095     /**
00096      * Loads a <myobject> from an opened file.
00097      * @param file the opened file from which to load.
00098      * @return 0 in case of success, error code otherwise.
00099      *
00100      * @sa load ()
00101      *
00102      */ 
00103     s_int8 get (igzstream& file);
00104 
00105     /**
00106      * Loads a <myobject> from it's filename.
00107      * 
00108      * @param fname the name of the file to load.
00109      * @return 0 in case of success, error code otherwise.
00110      *
00111      * @sa get ()
00112      */
00113     s_int8 load (string fname);
00114 
00115     /** 
00116      *  Saves a <myobject> into an opened file.
00117      *
00118      *  @param file opened file where to save into.
00119      *  @return 0 in case of success, error code otherwise.
00120      *
00121      *  @sa save ()
00122      */
00123     s_int8 put (ogzstream& file) const;
00124 
00125     /** Saves a <myobject> into a file from it's name.
00126      *  @param fname file name where to save into.
00127      *  @return 0 in case of success, error code otherwise.
00128      *
00129      *  @sa put ()
00130      */
00131     s_int8 save (string fname) const;
00132     //@}    
00133 
00134 
00135     /**
00136      * @name State loading/saving methods
00137      *
00138      */
00139     //@{
00140 
00141     /** 
00142      * Restore the <myobject> state from an opened file.
00143      * 
00144      * @param file the opened file from which to load the state.
00145      * @return 0 in case of success, error code otherwise.
00146      */
00147     s_int8 get_state (igzstream& file);
00148 
00149     /** 
00150      * Saves the <myobject> state into an opened file.
00151      * 
00152      * @param file the opened file where to the state.
00153      * @return 0 in case of success, error code otherwise.
00154      */
00155     s_int8 put_state (ogzstream& file) const;
00156 
00157     //@}
00158 
00159 
00160     ....
00161 
00162 }
00163 \endverbatim
00164 
00165 \section objreuse Making your objects reusable
00166 Another issue that can decrease the %game performance is %objects lifetime.
00167 Take our sample %animation class. Say that I've already loaded an %animation that
00168 I don't need anymore, and I need to load another one. If my %object doesn't have
00169 a cleaning method, I'll have to delete my %animation %object and reallocate another
00170 one. And destructor call + deallocation + allocation + constructor call = a lot of
00171 time wasted. This can easily be avoided if your %object has a cleaning method, that
00172 restores it to it's post-constructor state and allow you to reuse it as if it was 
00173 a new one. The loading method is a good place where to call this cleaning function,
00174 as you can't expect to load something if your %object isn't empty. In our %animation 
00175 sample class, the \e clear () method would delete the \e frames vector (cleaning up 
00176 the %datas) and put \e currentframe to 0 (safe, post-constructor state). And I now 
00177 can use the same %object multiple times. Most often too, the destructor will be a 
00178 simple call to clear (), as it also frees all the memory occupied by the %object.
00179 
00180 The declaration convention is quite straightforward then:
00181 \verbatim
00182 class myclass
00183 {
00184 public:
00185     ....
00186 
00187     /**
00188      * Puts the <myobject> back to it's post-constructor state.
00189      * 
00190      */ 
00191     void clear ();
00192 
00193     ....
00194 }
00195 \endverbatim
00196 
00197 Note that not every %object int the %game needs to be state-saveable. First, they must
00198 have a changeable state, and second, they have to be saved/loaded during %game 
00199 saving/loading.
00200 
00201 */

Generated on Mon Sep 12 2011 for Adonthell by  doxygen 1.7.1