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