1 /*
2    Copyright (C) 2001/2002 Kai Sterker <kai.sterker@gmail.com>
3    Part of the Adonthell Project <http://adonthell.nongnu.org>
4 
5    Adonthell is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9 
10    Adonthell is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14 
15    You should have received a copy of the GNU General Public License
16    along with Adonthell.  If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 /**
20  * @file gametime.h
21  *
22  * @author Kai Sterker
23  * @brief Declares the gametime class.
24  */
25 
26 #ifndef GAMETIME_H_
27 #define GAMETIME_H_
28 
29 #include "types.h"
30 
31 /**
32  * Length of a %game cycle, in milliseconds. Decrease it to speed up
33  * the %game, increase it to slow the %game down.  This constant
34  * defines how often the state of the game world is updated.
35  * A cycle length of 13 means 1000/13 = 76.9 updates per second.
36  */
37 #define CYCLE_LENGTH 13
38 
39 /**
40  * Number of maximum displayed frames per second. This value affects
41  * the renderer only, not the speed of the game itself. Limiting the
42  * frame rate prevents Adonthell from using all the CPU of the
43  * machine it runs on (as long as the machine is fast enough).
44  */
45 #define FRAME_RATE 50
46 
47 /**
48  * Defines the maximum number of frames to skip in order to keep the %game's
49  * speed constant on slow machines. If updating the %game state and
50  * drawing everything on %screen takes longer than CYCLE_LENGTH, we
51  * skip frames so that the correct number of updates can be performed,
52  * thus keeping the speed constant. However, we can't skip too many
53  * frames, since that would result in jerky animations and eventually
54  * render the %game unplayable.
55  */
56 #define FTS_LIMIT 20
57 
58 /**
59  * Tehe %gametime class makes the speed of the %game independent of
60  * the machine it runs on. This is achieved by keeping the number of
61  * updates to the %game state constant, no matter how fast or slow
62  * the machine. This won't work for very slow machines of course,
63  * but Adonthell will still be playable on a 100 Ghz CPU.
64  */
65 class gametime
66 {
67 public:
68     /**
69      * Initialize the gametime class.
70      *
71      * @param rt_minutes Defines how many real life minutes make one
72      *      gametime day.
73      */
74     static void init (u_int16 rt_minutes);
75 
76     /**
77      * Return the in-game time that passed since the last call to
78      * this method.
79      *
80      * @return %gametime in minutes.
81      */
minute()82     static double minute ()
83     {
84         return Minute;
85     }
86 
87     /**
88      *
89      */
start_action()90     static void start_action ()
91     {
92         fts = 0;
93         running = true;
94     }
95 
96     /**
97      *
98      */
stop_action()99     static void stop_action ()
100     {
101         running = false;
102     }
103 
104     /**
105      * @name Methods to sync the %game speed to the machine it runs on
106      */
107     //@{
108     /**
109      * Returns the number of updates to perform before drawing
110      * the next frame. That is, it returns the number of frames to skip.
111      * If the box Adonthell runs on is sufficiently fast, this number
112      * will be 0. On slower machines, it can be as high as FTS_LIMIT.
113      *
114      * @return number of updates to perform before drawing a frame.
115      * @see FTS_LIMIT
116      */
frames_to_skip()117     static u_int8 frames_to_skip ()
118     {
119         return fts;
120     }
121 
122     /**
123       * Call this after each run of the main loop to sync the %game's
124       * speed to the machine it is running on. On faster machines it
125       * delays the execution and for slower boxes it calculates the
126       * number of frames to skip. If the engine should do 50 frames per
127       * second, for example, but the main loop takes 26ms to perform,
128       * every second frame will be skipped to keep the %game' speed
129       * constant.
130       * It also updates the internal clock.
131       *
132       * @see frames_to_skip ()
133       */
134     static void update ();
135     //@}
136 
137 private:
138 #ifndef SWIG
139     // One minute of gametime in game cycles
140     static double Minute;
141 
142     static bool running;
143 
144     // Frames to skip.
145     static u_int8 fts;
146 
147     // Timers used to calculate the delay between 2 update() calls.
148     static u_int32 timer1, timer2;
149 #endif // SWIG
150 };
151 
152 #endif // GAMETIME_H_
153