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