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