update thread setup with a good cap
[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
ad9f1fb6
PG
34void init();
35
7cbd4505
PG
36void sighandler( int sig );
37
ad9f1fb6 38void run();
617dcc71 39void clean();
ad9f1fb6 40
ad9f1fb6
PG
41void updateFPSCounters();
42
68b2316d 43void handleInput();
ad9f1fb6
PG
44void update(float);
45void draw();
46
ad9f1fb6
PG
47/// ***** Private Variables *****
48
49// variable used to determine if it is time to shutdown
50bool is_Running;
51
52/* Values for the main game loop
53 * target_UPS := the amount of updates that is wanted in one second
ce53f20f 54 *
ad9f1fb6
PG
55 * ups := updates per second for the last second
56 * fps := frames per second for the last second
57 * update_Count := counts this seconds updates
58 * draw_Count := counts this seconds draws
59 * last_Second := stores the time of the last second, used for ups and fps
60 */
d279b77b 61int target_UPS = 100;
8baa4b2f 62float update_Wait = 0;
ad9f1fb6 63
ce53f20f 64int ups, fps;
ad9f1fb6 65int update_Count, draw_Count;
8baa4b2f
PG
66MICRO last_Second;
67
68const int min_wait_milli = 20;
69const int min_wait_micro = min_wait_milli * 1000;
70const float game_step = 10;
ad9f1fb6 71
ce53f20f
PG
72int startUpdateThread(void*);
73int startDrawThread(void*);
d279b77b 74
617dcc71 75/// ***** MAIN Method *****
3c3c195d 76int main(int argc, char** args)
617dcc71
PG
77{
78 init();
79 run();
80 clean();
81 return 0;
82}
83
84/// ***** Initializers/Cleaners *****
85
ad9f1fb6
PG
86void init()
87{
7cbd4505
PG
88 installSignal();
89
68b2316d 90 graphics::init();
5f3520c8 91 DPF(0, "Graphics initialized");
3c3c195d 92
68b2316d 93 game::init();
5f3520c8 94 DPF(0, "Game initialized");
3c3c195d 95
68b2316d 96 input::init();
5f3520c8 97 DPF(0, "Input initialized");
3c3c195d 98
b1d92c2f 99 cfg::init();
5f3520c8 100 DPF(0, "Configs initialized");
b1d92c2f 101
5f3520c8 102 DPF(0, "Initialization Complete");
ad9f1fb6
PG
103}
104
617dcc71 105void clean()
44b079f8 106{
ca2d526e 107 DPF(0, "Cleaning up");
44b079f8 108
b1d92c2f
PG
109 cfg::clean();
110
68b2316d 111 input::clean();
617dcc71 112
68b2316d 113 game::clean();
44b079f8 114
68b2316d 115 graphics::clean();
44b079f8
PG
116}
117
617dcc71
PG
118/// ***** Private Methods *****
119
ad9f1fb6
PG
120void run()
121{
122 is_Running = true;
d279b77b 123
ce53f20f 124 SDL_Thread* updates = SDL_CreateThread(startUpdateThread, NULL);
d279b77b 125
8baa4b2f 126 // for some reason this needs to be on the main thread ...?
ce53f20f 127 startDrawThread(NULL);
ad9f1fb6 128
ce53f20f 129 SDL_WaitThread(updates, NULL);
ad9f1fb6
PG
130}
131
132void updateFPSCounters()
133{
134 // Check if a second has passed to recalculate UPS and FPS
135 if (tickCountMicro() - last_Second >= 1000000)
136 {
137 ups = update_Count;
138 fps = draw_Count;
ce53f20f
PG
139
140 // NOT thread safe, but they're estimates anyways
141 update_Count -= ups;
142 draw_Count -= fps;
ad9f1fb6
PG
143
144 last_Second = tickCountMicro();
44b079f8 145
7adc59fe
PG
146#ifdef FPSUPS
147 cout << "ups:\t" << ups << endl;
148 cout << "fps:\t" << fps << endl;
149#endif
ad9f1fb6
PG
150 }
151}
152
68b2316d 153void handleInput()
ad9f1fb6 154{
ce53f20f 155 input::update();
f7b3b2eb 156
ce53f20f 157 game::handleInput();
ad9f1fb6 158
ce53f20f
PG
159 if(cfg::endGame())
160 is_Running = false;
ad9f1fb6
PG
161}
162
163void update(float time_step)
164{
ce53f20f 165 game::update(time_step);
ad9f1fb6 166 update_Count++;
ad9f1fb6
PG
167}
168
169void draw()
170{
ce53f20f 171 game::draw();
d279b77b 172
ce53f20f
PG
173 SDL_GL_SwapBuffers();
174
175 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
ad9f1fb6 176
ce53f20f
PG
177 draw_Count++;
178}
d279b77b 179
ce53f20f
PG
180int startUpdateThread(void*)
181{
8baa4b2f
PG
182 last_Second = tickCountMicro();
183
ce53f20f
PG
184 while(is_Running)
185 {
8baa4b2f
PG
186 MICRO time = tickCountMicro();
187 handleInput();
188 update(game_step);
189
190 updateFPSCounters();
191 time = tickCountMicro() - time;
d279b77b 192
8baa4b2f
PG
193 float wait = (1000000.0 / target_UPS - time);
194 update_Wait += 0 < wait ? wait : 0;
d279b77b 195
8baa4b2f
PG
196 while(min_wait_micro < update_Wait)
197 {
198 update_Wait -= min_wait_micro;
199 SDL_Delay(min_wait_milli);
200 }
ce53f20f 201 }
ad9f1fb6 202
ce53f20f
PG
203 return 0;
204}
ad9f1fb6 205
ce53f20f
PG
206int startDrawThread(void*)
207{
208 while(is_Running)
209 {
210 draw();
211 }
25d84412 212
ce53f20f 213 return 0;
ad9f1fb6 214}