changes needed due to library cleaning
[physics.git] / src / main.cpp
... / ...
CommitLineData
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 <pg/debug.h>
19using namespace pg;
20
21#include <iostream>
22using std::cout;
23using std::endl;
24
25#include <GL/gl.h>
26#include <GL/glu.h>
27#include <SDL/SDL.h>
28
29#include "handleSignal.h"
30
31#include "game.h"
32#include "ticks.h"
33
34#include "graphics/graphics.h"
35#include "input/inputManager.h"
36#include "config/config.h"
37
38/// ***** Private Method Headers *****
39
40static void mainInit();
41static void mainClean();
42
43static void updatesInit();
44static void updatesClean();
45
46static void drawInit();
47static void drawClean();
48
49static void run();
50
51static void updateFPSCounters();
52
53static void handleInput();
54static void update(float);
55static void draw();
56
57static int startUpdateThread(void*);
58static int startDrawThread(void*);
59
60/// ***** Private Variables *****
61
62// variable used to determine if it is time to shutdown
63static bool s_bIsRunning;
64
65// Minimum possible wait times by used library
66static const int s_iMinWaitMilli = 20;
67static const int s_iMinWaitMicro = s_iMinWaitMilli * 1000;
68
69/* Values for the main game loop
70 *
71 * s_iTargetUPS := the amount of updates that is wanted in one second
72 * s_fAccUpdateWait := the accumulated wait time for the update sleeps
73 *
74 * s_iUPS := updates per second for the last second
75 * s_iFPS := frames per second for the last second
76 * s_iUpdateCount := counts this seconds updates
77 * s_iDrawCount := counts this seconds draws
78 * s_micLastSecond := stores the time of the last second, used for ups and fps
79 */
80static int s_iTargetUPS = 100;
81static float s_fAccUpdateWait = 0;
82
83static int s_iTargetFPS = 100;
84static float s_fAccDrawWait = 0;
85
86static int s_iUPS, s_iFPS;
87static int s_iUpdateCount, s_iDrawCount;
88static MICRO s_micLastSecond;
89
90static const float s_fGameStep = 10;
91
92static bool s_bUpdateInitialized = false;
93static bool s_bDrawInitialized = false;
94
95/// ***** MAIN Method *****
96int main(int argc, char** args)
97{
98 mainInit();
99 run();
100 mainClean();
101
102 return 0;
103}
104
105/// ***** Initializers/Cleaners *****
106
107void mainInit()
108{
109 installSignal();
110
111 debug::init();
112}
113void mainClean()
114{
115 debug::deinit();
116}
117
118void updatesInit()
119{
120 while(!s_bDrawInitialized)
121 SDL_Delay(100);
122
123 game::init();
124 DPF(0, "Game initialized");
125
126 input::init();
127 DPF(0, "Input initialized");
128
129 cfg::init();
130 DPF(0, "Configs initialized");
131
132 DPF(0, "Initialization Complete");
133
134 s_bUpdateInitialized = true;
135}
136void updatesClean()
137{
138 DPF(0, "Update Thread Cleaning");
139
140 cfg::clean();
141
142 input::clean();
143
144 game::clean();
145}
146
147void drawInit()
148{
149 graphics::init();
150 DPF(0, "Graphics initialized");
151
152 s_bDrawInitialized = true;
153
154 while(!s_bUpdateInitialized)
155 SDL_Delay(100);
156}
157void drawClean()
158{
159 DPF(0, "Draw Thread Cleaning");
160
161 graphics::clean();
162}
163
164/// ***** Private Methods *****
165
166void run()
167{
168 s_bIsRunning = true;
169
170 SDL_Thread* s_pUpdatesThread = SDL_CreateThread(startUpdateThread, NULL);
171 SDL_Thread* s_pDrawThread = SDL_CreateThread(startDrawThread, NULL);
172
173 SDL_WaitThread(s_pUpdatesThread, NULL);
174 SDL_WaitThread(s_pDrawThread, NULL);
175}
176
177void updateFPSCounters()
178{
179 // Check if a second has passed to recalculate UPS and FPS
180 if (tickCountMicro() - s_micLastSecond >= 1000000)
181 {
182 s_iUPS = s_iUpdateCount;
183 s_iFPS = s_iDrawCount;
184
185 // NOT thread safe, but they're estimates anyways
186 s_iUpdateCount -= s_iUPS;
187 s_iDrawCount -= s_iFPS;
188
189 s_micLastSecond = tickCountMicro();
190
191 if(cfg::showFPS())
192 {
193 cout << "fps:\t" << s_iFPS << endl;
194 }
195 if(cfg::showUPS())
196 {
197 cout << "ups:\t" << s_iUPS << endl;
198 }
199 }
200}
201
202void handleInput()
203{
204 input::update();
205
206 cfg::handleInput();
207 game::handleInput();
208
209 if(cfg::endGame())
210 s_bIsRunning = false;
211}
212
213void update(float fTimeStep)
214{
215 game::update(fTimeStep);
216 s_iUpdateCount++;
217}
218
219void draw()
220{
221 game::draw();
222
223 SDL_PumpEvents(); // has to be on the Draw thread for the Windows API
224
225 SDL_GL_SwapBuffers();
226
227 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
228
229 s_iDrawCount++;
230}
231
232int startUpdateThread(void*)
233{
234 updatesInit();
235
236 s_micLastSecond = tickCountMicro();
237
238 while(s_bIsRunning)
239 {
240 MICRO time = tickCountMicro();
241 handleInput();
242 update(s_fGameStep);
243
244 updateFPSCounters();
245 time = tickCountMicro() - time;
246
247 float wait = (1000000.0 / s_iTargetUPS - time);
248 s_fAccUpdateWait += 0 < wait ? wait : 0;
249
250 if(s_iMinWaitMicro < s_fAccUpdateWait)
251 {
252 int iWaits = (int)(s_fAccUpdateWait / s_iMinWaitMicro);
253 s_fAccUpdateWait -= iWaits * s_iMinWaitMicro;
254 SDL_Delay(iWaits * s_iMinWaitMilli);
255 }
256 }
257
258 updatesClean();
259
260 return 0;
261}
262
263int startDrawThread(void*)
264{
265 drawInit();
266
267 while(s_bIsRunning)
268 {
269 MICRO time = tickCountMicro();
270 draw();
271 time = tickCountMicro() - time;
272
273 float wait = (1000000.0 / s_iTargetFPS - time);
274 s_fAccDrawWait += 0 < wait ? wait : 0;
275
276 if(s_iMinWaitMicro < s_fAccDrawWait)
277 {
278 int iWaits = (int)(s_fAccDrawWait / s_iMinWaitMicro);
279 s_fAccDrawWait -= iWaits * s_iMinWaitMicro;
280 SDL_Delay(iWaits * s_iMinWaitMilli);
281 }
282 }
283
284 drawClean();
285
286 return 0;
287}