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