Adonthell  0.4
save.dxt
1 /*
2  $Id: save.dxt,v 1.1 2001/10/15 15:00:06 gnurou Exp $
3 
4  Copyright (C) 2001 Alexandre Courbot
5  Part of the Adonthell Project http://adonthell.linuxgames.com
6 
7  This program is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 /*!
16 
17 \page page6 Saving/Loading
18 
19 \section objdatobjst Object data and object state
20 
21 This is another important part of the %game engine. Quite a few %objects should
22 be loadable and saveable, but there is a difference between two things
23 that may look like one: an %object's %data itself and an %object's state.
24 
25 But there is a significant difference. Data is all the information that stays
26 the same during an %object's lifetime. As a consequence, %data remains persistent
27 over the whole %game. An %object's state is the information that changes while the
28 %game progresses.
29 
30 For example, when loading a map, all the actual graphics are persistant %data.
31 OTOH, player and NPC's are certainly no longer at their initial position, so
32 this information belongs to the map's state.
33 
34 Let's see precisely how it works with a simple %animation class:
35 
36 \verbatim
37 class animation
38 {
39 public:
40  // Constructor / Destructor.
41  animation ();
42  ~animation ();
43 
44  .....
45 
46  // Saving / Loading methods.
47  void get (FILE * in);
48  void put (FILE * out);
49 
50  // State saving / loading methods.
51  void get_state (FILE * in);
52  void put_state (FILE * out);
53 
54 private:
55  vector <image> frames;
56 
57  u_int32 currentframe;
58 }
59 \endverbatim
60 
61 The difference between the %object %data and the %object state is quite obvious here: the
62 \e frames vector is an array containing the raw %images - they won't change during
63 gameplay, so they are considered as the %object \e %data, while the \e currentframe
64 member will change during the %game, and actually when we load a %game we would like
65 it to have the same value than when we saved it. That's why \e get and \e put will
66 save the \e frames vector (and maybe put \e currentframe to 0 for \e get, to make sure
67 the %object is in a stable state), and \e get_state and \e put_state will save/load the
68 currentframe member. That way, when you load a %game, you can simply get the %object state
69 from the save file, while the %object itself will be loaded from the %data directory.
70 
71 \section convsave Conventions for saving/loading methods
72 To reduce the amount of space needed for the %game, loading/saving methods use the igzstream
73 and ogzstream classes for disk access. See their own documentation for more details.
74 
75 The saving methods should be constant - that is, they doesn't change the state of the %object
76 itself. The loading methods should always bring the %object into a stable state once they
77 return (think of what would happen if you load an %animation and the \e currenframe member
78 remains with a value superior to the actual number of %images in this %animation). The
79 declaration conventions are the following (you can use this template declaration for your
80 own classes, as it also shows you the proper way to document your code with sections):
81 
82 \verbatim
83 class myclass
84 {
85 public:
86 
87 .....
88 
89  /**
90  * @name Loading/Saving methods
91  *
92  */
93  //@{
94 
95  /**
96  * Loads a <myobject> from an opened file.
97  * @param file the opened file from which to load.
98  * @return 0 in case of success, error code otherwise.
99  *
100  * @sa load ()
101  *
102  */
103  s_int8 get (igzstream& file);
104 
105  /**
106  * Loads a <myobject> from it's filename.
107  *
108  * @param fname the name of the file to load.
109  * @return 0 in case of success, error code otherwise.
110  *
111  * @sa get ()
112  */
113  s_int8 load (string fname);
114 
115  /**
116  * Saves a <myobject> into an opened file.
117  *
118  * @param file opened file where to save into.
119  * @return 0 in case of success, error code otherwise.
120  *
121  * @sa save ()
122  */
123  s_int8 put (ogzstream& file) const;
124 
125  /** Saves a <myobject> into a file from it's name.
126  * @param fname file name where to save into.
127  * @return 0 in case of success, error code otherwise.
128  *
129  * @sa put ()
130  */
131  s_int8 save (string fname) const;
132  //@}
133 
134 
135  /**
136  * @name State loading/saving methods
137  *
138  */
139  //@{
140 
141  /**
142  * Restore the <myobject> state from an opened file.
143  *
144  * @param file the opened file from which to load the state.
145  * @return 0 in case of success, error code otherwise.
146  */
147  s_int8 get_state (igzstream& file);
148 
149  /**
150  * Saves the <myobject> state into an opened file.
151  *
152  * @param file the opened file where to the state.
153  * @return 0 in case of success, error code otherwise.
154  */
155  s_int8 put_state (ogzstream& file) const;
156 
157  //@}
158 
159 
160  ....
161 
162 }
163 \endverbatim
164 
165 \section objreuse Making your objects reusable
166 Another issue that can decrease the %game performance is %objects lifetime.
167 Take our sample %animation class. Say that I've already loaded an %animation that
168 I don't need anymore, and I need to load another one. If my %object doesn't have
169 a cleaning method, I'll have to delete my %animation %object and reallocate another
170 one. And destructor call + deallocation + allocation + constructor call = a lot of
171 time wasted. This can easily be avoided if your %object has a cleaning method, that
172 restores it to it's post-constructor state and allow you to reuse it as if it was
173 a new one. The loading method is a good place where to call this cleaning function,
174 as you can't expect to load something if your %object isn't empty. In our %animation
175 sample class, the \e clear () method would delete the \e frames vector (cleaning up
176 the %datas) and put \e currentframe to 0 (safe, post-constructor state). And I now
177 can use the same %object multiple times. Most often too, the destructor will be a
178 simple call to clear (), as it also frees all the memory occupied by the %object.
179 
180 The declaration convention is quite straightforward then:
181 \verbatim
182 class myclass
183 {
184 public:
185  ....
186 
187  /**
188  * Puts the <myobject> back to it's post-constructor state.
189  *
190  */
191  void clear ();
192 
193  ....
194 }
195 \endverbatim
196 
197 Note that not every %object int the %game needs to be state-saveable. First, they must
198 have a changeable state, and second, they have to be saved/loaded during %game
199 saving/loading.
200 
201 */