8c3134bd177fb8efaf72051b155c69ab91b49bf5
[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, fps;
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
87 /// ***** MAIN Method *****
88 int main()
89 {
90     init();
91     run();
92     clean();
93     return 0;
94 }
95
96 /// ***** Initializers/Cleaners *****
97
98 void init()
99 {
100     installSignal();
101
102     graphics::init();
103
104     game::init();
105
106     input::init();
107
108     cfg::init();
109
110 #ifdef DEBUGGING
111     cout << "Initialization Complete" << endl;
112 #endif
113 }
114
115 void clean()
116 {
117 #ifdef DEBUGGING
118     cout << "Cleaning up" << endl;
119 #endif
120
121     cfg::clean();
122
123     input::clean();
124
125     game::clean();
126
127     graphics::clean();
128 }
129
130 /// ***** Private Methods *****
131
132 float total = 0;
133
134 void run()
135 {
136     is_Running = true;
137     last_Block_Update = tickCountMicro();
138     last_Second = tickCountMicro();
139
140     while(is_Running)
141     {
142         long int time;
143
144         time = tickCountMicro();
145             blockUpdate();
146             updateFPSCounters();
147             draw();
148         time = tickCountMicro() - time;
149
150         rRun = (rRun * (num-1) + time) / num;
151
152         //cout << "total:\t" << total << endl;
153         //cout << "rR:\t" << rRun << endl;
154         //total = 0;
155     }
156 }
157
158 void blockUpdate()
159 {
160     long int start = tickCountMicro();
161
162     //cout << "Block" << endl;
163
164     // Calculate the updates that should be run for the next draw
165     update_Sum += (start - last_Block_Update) / (1000000 / (float)target_UPS);
166
167     // insures the float to int cast is done once.
168     int iupdate_sum = (int)update_Sum;
169
170     // TODO the main run loop needs to be tested and pruned
171     if (iupdate_sum > 0)
172     {
173         // Calculate a time step that spreads the updates out as much as possible
174         // used because really quick updates are nearly wasted
175         float time_step = ((float)(start - last_Block_Update)) / iupdate_sum / 1000;
176
177         // run the updates
178         for (int i = 1; i <= iupdate_sum; i++)
179         {
180             handleInput();
181             update(time_step);
182         }
183         // remove the updates that where run from the sum
184         update_Sum -= iupdate_sum;
185         last_Block_Update = tickCountMicro();
186     }
187 }
188
189 void updateFPSCounters()
190 {
191     // Check if a second has passed to recalculate UPS and FPS
192     if (tickCountMicro() - last_Second >= 1000000)
193     {
194         ups = update_Count;
195         fps = draw_Count;
196         times = time_steps_Count;
197         update_Count = 0;
198         draw_Count = 0;
199         time_steps_Count = 0;
200
201         last_Second = tickCountMicro();
202
203 #ifdef FPSUPS
204         cout << "ups:\t" << ups << endl;
205         cout << "fps:\t" << fps << endl;
206         cout << "times:\t" << times << endl;
207 #endif
208     }
209 }
210
211 void handleInput()
212 {
213     long int time;
214
215     time = tickCountMicro();
216         input::update();
217
218         game::handleInput();
219
220         if(cfg::endGame())
221             is_Running = false;
222     time = tickCountMicro() - time;
223
224     rInput = (rInput*(num-1) + time) /num;
225
226     total += rInput;
227 }
228
229 void update(float time_step)
230 {
231     long int time;
232
233     update_Count++;
234     time_steps_Count += time_step;
235
236     time = tickCountMicro();
237         game::update(time_step);
238     time = tickCountMicro() - time;
239
240     rUpdate = (rUpdate * (num-1) + time) / num;
241
242     //cout << "ts:\t" << time_step << endl;
243     //cout << "ru:\t" << rUpdate << endl;
244
245     total += rUpdate;
246 }
247
248 void draw()
249 {
250     long int time;
251
252     draw_Count++;
253
254     time = tickCountMicro();
255         game::draw();
256
257         SDL_GL_SwapBuffers();
258
259         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
260
261 //        SDL_Delay(20);
262     time = tickCountMicro() - time;
263
264     rDraw = (rDraw*(num-1) + time) /num;
265
266     //cout << "rd:\t" << rDraw << endl;
267
268     total += rDraw;
269 }