File: save.dxt

package info (click to toggle)
adonthell 0.3.8-5
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 5,416 kB
  • sloc: cpp: 50,659; sh: 5,142; python: 3,307; makefile: 338; lex: 216; sed: 16
file content (201 lines) | stat: -rw-r--r-- 6,435 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
/*
   $Id$

   Copyright (C) 2001   Alexandre Courbot
   Part of the Adonthell Project http://adonthell.linuxgames.com

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License.
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY.

   See the COPYING file for more details.
*/

/*! 

\page page6 Saving/Loading

\section objdatobjst Object data and object state

This is another important part of the %game engine. Quite a few %objects should
be loadable and saveable, but there is a difference between two things
that may look like one: an %object's %data itself and an %object's state.

But there is a significant difference. Data is all the information that stays
the same during an %object's lifetime. As a consequence, %data remains persistent
over the whole %game. An %object's state is the information that changes while the
%game progresses.

For example, when loading a map, all the actual graphics are persistant %data.
OTOH, player and NPC's are certainly no longer at their initial position, so
this information belongs to the map's state.

Let's see precisely how it works with a simple %animation class:

\verbatim
class animation
{
public:
    // Constructor / Destructor.
    animation ();
    ~animation ();

    .....

    // Saving / Loading methods.
    void get (FILE * in);
    void put (FILE * out);

    // State saving / loading methods.
    void get_state (FILE * in);
    void put_state (FILE * out);

private:
    vector <image> frames;

    u_int32 currentframe;
}
\endverbatim

The difference between the %object %data and the %object state is quite obvious here: the
\e frames vector is an array containing the raw %images - they won't change during 
gameplay, so they are considered as the %object \e %data, while the \e currentframe
member will change during the %game, and actually when we load a %game we would like
it to have the same value than when we saved it. That's why \e get and \e put will
save the \e frames vector (and maybe put \e currentframe to 0 for \e get, to make sure
the %object is in a stable state), and \e get_state and \e put_state will save/load the 
currentframe member. That way, when you load a %game, you can simply get the %object state
from the save file, while the %object itself will be loaded from the %data directory.

\section convsave Conventions for saving/loading methods
To reduce the amount of space needed for the %game, loading/saving methods use the igzstream
and ogzstream classes for disk access. See their own documentation for more details.

The saving methods should be constant - that is, they doesn't change the state of the %object
itself. The loading methods should always bring the %object into a stable state once they 
return (think of what would happen if you load an %animation and the \e currenframe member
remains with a value superior to the actual number of %images in this %animation). The 
declaration conventions are the following (you can use this template declaration for your
own classes, as it also shows you the proper way to document your code with sections):

\verbatim
class myclass
{
public:

.....

    /**
     * @name Loading/Saving methods
     *
     */
    //@{
        
    /**
     * Loads a <myobject> from an opened file.
     * @param file the opened file from which to load.
     * @return 0 in case of success, error code otherwise.
     *
     * @sa load ()
     *
     */ 
    s_int8 get (igzstream& file);

    /**
     * Loads a <myobject> from it's filename.
     * 
     * @param fname the name of the file to load.
     * @return 0 in case of success, error code otherwise.
     *
     * @sa get ()
     */
    s_int8 load (string fname);

    /** 
     *  Saves a <myobject> into an opened file.
     *
     *  @param file opened file where to save into.
     *  @return 0 in case of success, error code otherwise.
     *
     *  @sa save ()
     */
    s_int8 put (ogzstream& file) const;

    /** Saves a <myobject> into a file from it's name.
     *  @param fname file name where to save into.
     *  @return 0 in case of success, error code otherwise.
     *
     *  @sa put ()
     */
    s_int8 save (string fname) const;
    //@}    


    /**
     * @name State loading/saving methods
     *
     */
    //@{

    /** 
     * Restore the <myobject> state from an opened file.
     * 
     * @param file the opened file from which to load the state.
     * @return 0 in case of success, error code otherwise.
     */
    s_int8 get_state (igzstream& file);

    /** 
     * Saves the <myobject> state into an opened file.
     * 
     * @param file the opened file where to the state.
     * @return 0 in case of success, error code otherwise.
     */
    s_int8 put_state (ogzstream& file) const;

    //@}


    ....

}
\endverbatim

\section objreuse Making your objects reusable
Another issue that can decrease the %game performance is %objects lifetime.
Take our sample %animation class. Say that I've already loaded an %animation that
I don't need anymore, and I need to load another one. If my %object doesn't have
a cleaning method, I'll have to delete my %animation %object and reallocate another
one. And destructor call + deallocation + allocation + constructor call = a lot of
time wasted. This can easily be avoided if your %object has a cleaning method, that
restores it to it's post-constructor state and allow you to reuse it as if it was 
a new one. The loading method is a good place where to call this cleaning function,
as you can't expect to load something if your %object isn't empty. In our %animation 
sample class, the \e clear () method would delete the \e frames vector (cleaning up 
the %datas) and put \e currentframe to 0 (safe, post-constructor state). And I now 
can use the same %object multiple times. Most often too, the destructor will be a 
simple call to clear (), as it also frees all the memory occupied by the %object.

The declaration convention is quite straightforward then:
\verbatim
class myclass
{
public:
    ....

    /**
     * Puts the <myobject> back to it's post-constructor state.
     * 
     */ 
    void clear ();

    ....
}
\endverbatim

Note that not every %object int the %game needs to be state-saveable. First, they must
have a changeable state, and second, they have to be saved/loaded during %game 
saving/loading.

*/