1e9d4ad7e0b916915b5bd5cfa247d77f05eb7649
[physics.git] / src / main.cpp
1 /*
2  *  Copyright (C) 2008 Patrik Gornicz, Gornicz_P (at) hotmail (dot) com.
3  *
4  *  This program is free software: you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation, either version 3 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 #include <GL/gl.h>
19 #include <GL/glu.h>
20 #include <SDL/SDL.h>
21
22 #include "debug.h"
23 #include "handleSignal.h"
24
25 #include "game.h"
26 #include "ticks.h"
27
28 #include "graphics/graphics.h"
29 #include "input/inputManager.h"
30 #include "config/config.h"
31
32 /// ***** Private Method Headers *****
33
34 void init();
35
36 void sighandler( int sig );
37
38 void run();
39 void clean();
40
41 void blockUpdate();
42 void updateFPSCounters();
43
44 void handleInput();
45 void update(float);
46 void draw();
47
48 /// ***** Private Variables *****
49
50 // variable used to determine if it is time to shutdown
51 bool is_Running;
52
53 /* Values for the main game loop
54  * target_UPS := the amount of updates that is wanted in one second
55  * last_Update := stores the time of the last update
56  * update_Sum := used to determine the updates needs for this run
57
58  * ups := updates per second for the last second
59  * fps := frames per second for the last second
60  * update_Count := counts this seconds updates
61  * draw_Count  := counts this seconds draws
62  * last_Second := stores the time of the last second, used for ups and fps
63  */
64 int target_UPS = 100;
65 long int last_Block_Update;
66 float update_Sum = 0;
67
68 int ups=100, fps=100;
69 int update_Count, draw_Count;
70 long int last_Second;
71
72
73 float target_time_steps_per_second = 1000;
74 float times;
75 float time_steps_Count;
76
77
78 // experiment with rolling averages
79 float rUpdate = 100;
80 float rDraw = 100;
81 float rInput = 100;
82 float rRun = 100;
83
84 float num = 10;
85
86 float total = 0;
87
88 /// ***** MAIN Method *****
89 int main(int argc, char** args)
90 {
91     init();
92     run();
93     clean();
94     return 0;
95 }
96
97 /// ***** Initializers/Cleaners *****
98
99 void init()
100 {
101     installSignal();
102
103     graphics::init();
104
105 #ifdef DEBUGGING
106     cout << "Graphics initialized" << endl;
107     cout << "Graphics initialized2" << endl;
108 #endif
109
110     game::init();
111
112 #ifdef DEBUGGING
113     cout << "Game initialized" << endl;
114 #endif
115
116     input::init();
117
118 #ifdef DEBUGGING
119     cout << "Input initialized" << endl;
120 #endif
121
122     cfg::init();
123
124 #ifdef DEBUGGING
125     cout << "Configs initialized" << endl;
126 #endif
127
128 #ifdef DEBUGGING
129     cout << "Initialization Complete" << endl;
130 #endif
131 }
132
133 void clean()
134 {
135 #ifdef DEBUGGING
136     cout << "Cleaning up" << endl;
137 #endif
138
139     cfg::clean();
140
141     input::clean();
142
143     game::clean();
144
145     graphics::clean();
146 }
147
148 /// ***** Private Methods *****
149
150 void run()
151 {
152     is_Running = true;
153     last_Block_Update = tickCountMicro();
154     last_Second = tickCountMicro();
155
156     while(is_Running)
157     {
158         long int time;
159
160         time = tickCountMicro();
161             blockUpdate();
162             updateFPSCounters();
163             draw();
164         time = tickCountMicro() - time;
165
166         rRun = (rRun * (num-1) + time) / num;
167
168         //cout << "total:\t" << total << endl;
169         //cout << "rR:\t" << rRun << endl;
170         //total = 0;
171     }
172 }
173
174 void blockUpdate()
175 {
176     long int start = tickCountMicro();
177     long int diff = start - last_Block_Update;
178
179     //cout << "Block" << endl;
180
181     // Calculate the updates that should be run for the next draw
182     update_Sum += (float)(diff * target_UPS) / 1000000;
183
184     // insures the float to int cast is done once.
185     int iupdate_sum = (int)update_Sum;
186
187     // TODO the main run loop needs to be tested and pruned
188     if (iupdate_sum > 0)
189     {
190         // Calculate a time step that spreads the updates out as much as
191         // possible used because really quick updates are nearly wasted
192
193         //float time_step = ((float)diff) / iupdate_sum / 1000;
194         //float time_step = 1000 / (100000 / rUpdate) / iupdate_sum;
195         //float time_step = 1000 / ups / iupdate_sum;
196         float time_step = 10;
197
198         // run the updates
199         for (int i = 0; i < iupdate_sum; i++)
200         {
201             handleInput();
202             update(time_step);
203         }
204
205         // remove the updates that were run from the sum
206         update_Sum -= iupdate_sum;
207         last_Block_Update = tickCountMicro();
208     }
209 }
210
211 void updateFPSCounters()
212 {
213     // Check if a second has passed to recalculate UPS and FPS
214     if (tickCountMicro() - last_Second >= 1000000)
215     {
216         ups = update_Count;
217         fps = draw_Count;
218         times = time_steps_Count;
219         update_Count = 0;
220         draw_Count = 0;
221         time_steps_Count = 0;
222
223         last_Second = tickCountMicro();
224
225 #ifdef FPSUPS
226         cout << "ups:\t" << ups << endl;
227         cout << "fps:\t" << fps << endl;
228         cout << "times:\t" << times << endl;
229 #endif
230     }
231 }
232
233 void handleInput()
234 {
235     long int time;
236
237     time = tickCountMicro();
238         input::update();
239
240         game::handleInput();
241
242         if(cfg::endGame())
243             is_Running = false;
244     time = tickCountMicro() - time;
245
246     rInput = (rInput*(num-1) + time) /num;
247
248     total += rInput;
249 }
250
251 void update(float time_step)
252 {
253     long int time;
254
255     update_Count++;
256     time_steps_Count += time_step;
257
258     time = tickCountMicro();
259         game::update(time_step);
260     time = tickCountMicro() - time;
261
262     rUpdate = (rUpdate * (num-1) + time) / num;
263
264     //cout << "ts:\t" << time_step << endl;
265     //cout << "ru:\t" << rUpdate << endl;
266
267     total += rUpdate;
268 }
269
270 void draw()
271 {
272     long int time;
273
274     draw_Count++;
275
276     time = tickCountMicro();
277         game::draw();
278
279         SDL_GL_SwapBuffers();
280
281         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
282
283         //SDL_Delay(10);
284     time = tickCountMicro() - time;
285
286     rDraw = (rDraw*(num-1) + time) /num;
287
288     //cout << "rd:\t" << rDraw << endl;
289
290     total += rDraw;
291 }