2 * Copyright (C) 2008 Patrik Gornicz, Gornicz_P (at) hotmail (dot) com.
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.
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.
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/>.
18 #include <bear/debug.h>
19 #include <bear/Timer.h>
30 #include "handleSignal.h"
34 #include "graphics/graphics.h"
35 #include "input/inputManager.h"
36 #include "config/config.h"
38 /// ***** Private Method Headers *****
40 static void mainInit();
41 static void mainClean();
43 static void updatesInit();
44 static void updatesClean();
46 static void drawInit();
47 static void drawClean();
51 static void updateFPSCounters();
53 static void handleInput();
54 static void update(float);
57 static int startUpdateThread(void*);
58 static int startDrawThread(void*);
60 /// ***** Private Variables *****
62 // variable used to determine if it is time to shutdown
63 static bool s_bIsRunning;
65 // Minimum possible wait times by used library
66 static const int s_iMinWaitMilli = 20;
67 static const int s_iMinWaitMicro = s_iMinWaitMilli * 1000;
69 /* Values for the main game loop
71 * s_iTargetUPS := the amount of updates that is wanted in one second
72 * s_fAccUpdateWait := the accumulated wait time for the update sleeps
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
80 static int s_iTargetUPS = 100;
81 static float s_fAccUpdateWait = 0;
83 static int s_iTargetFPS = 100;
84 static float s_fAccDrawWait = 0;
86 static int s_iUPS, s_iFPS;
87 static int s_iUpdateCount, s_iDrawCount;
89 static Ticks s_micLastSecond;
92 static const float s_fGameStep = 10;
94 static bool s_bUpdateInitialized = false;
95 static bool s_bDrawInitialized = false;
97 /// ***** MAIN Method *****
98 int main(int /*argc*/, char** /*args*/)
107 /// ***** Initializers/Cleaners *****
126 while(!s_bDrawInitialized)
130 DPF(0, "Game initialized");
133 DPF(0, "Input initialized");
136 DPF(0, "Configs initialized");
138 DPF(0, "Initialization Complete");
140 s_bUpdateInitialized = true;
144 DPF(0, "Update Thread Cleaning");
156 DPF(0, "Graphics initialized");
158 s_bDrawInitialized = true;
160 while(!s_bUpdateInitialized)
165 DPF(0, "Draw Thread Cleaning");
170 /// ***** Private Methods *****
176 SDL_Thread* s_pUpdatesThread = SDL_CreateThread(startUpdateThread, NULL);
177 SDL_Thread* s_pDrawThread = SDL_CreateThread(startDrawThread, NULL);
179 SDL_WaitThread(s_pUpdatesThread, NULL);
180 SDL_WaitThread(s_pDrawThread, NULL);
183 void updateFPSCounters()
185 // Check if a second has passed to recalculate UPS and FPS
186 if (s_timer.query() - s_micLastSecond >= 1000000)
188 s_iUPS = s_iUpdateCount;
189 s_iFPS = s_iDrawCount;
191 // NOT thread safe, but they're estimates anyways
192 s_iUpdateCount -= s_iUPS;
193 s_iDrawCount -= s_iFPS;
195 s_micLastSecond = s_timer.query();
199 cout << "fps:\t" << s_iFPS << endl;
203 cout << "ups:\t" << s_iUPS << endl;
216 s_bIsRunning = false;
219 void update(float fTimeStep)
221 game::update(fTimeStep);
229 SDL_PumpEvents(); // has to be on the Draw thread for the Windows API
231 SDL_GL_SwapBuffers();
233 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
238 int startUpdateThread(void*)
242 s_micLastSecond = s_timer.query();
252 const Ticks ticks = timer.query();
255 float wait = (1000000.0 / s_iTargetUPS - ticks.microseconds());
256 s_fAccUpdateWait += 0 < wait ? wait : 0;
258 if(s_iMinWaitMicro < s_fAccUpdateWait)
260 int iWaits = (int)(s_fAccUpdateWait / s_iMinWaitMicro);
261 s_fAccUpdateWait -= iWaits * s_iMinWaitMicro;
262 SDL_Delay(iWaits * s_iMinWaitMilli);
271 int startDrawThread(void*)
280 const Ticks ticks = timer.query();
283 float wait = (1000000.0 / s_iTargetFPS - ticks.microseconds());
284 s_fAccDrawWait += 0 < wait ? wait : 0;
286 if(s_iMinWaitMicro < s_fAccDrawWait)
288 int iWaits = (int)(s_fAccDrawWait / s_iMinWaitMicro);
289 s_fAccDrawWait -= iWaits * s_iMinWaitMicro;
290 SDL_Delay(iWaits * s_iMinWaitMilli);