added GPL copyrights
[physics.git] / src / main.cpp
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 <GL/gl.h>
19 #include <GL/glu.h>
20 #include <SDL/SDL.h>
21
22 #include "debug.h"
23 #include "handleSignal.h"
24
25 #include "game.h"
26 #include "ticks.h"
27
28 #include "graphics/graphics.h"
29 #include "input/inputManager.h"
30
31 /// ***** Private Method Headers *****
32
33 void init();
34
35 void sighandler( int sig );
36
37 void run();
38 void clean();
39
40 void blockUpdate();
41 void updateFPSCounters();
42
43 void handleInput();
44 void update(float);
45 void draw();
46
47 /// ***** Private Variables *****
48
49 // variable used to determine if it is time to shutdown
50 bool is_Running;
51
52 /* Values for the main game loop
53  * target_UPS := the amount of updates that is wanted in one second
54  * last_Update := stores the time of the last update
55  * update_Sum := used to determine the updates needs for this run
56
57  * ups := updates per second for the last second
58  * fps := frames per second for the last second
59  * update_Count := counts this seconds updates
60  * draw_Count  := counts this seconds draws
61  * last_Second := stores the time of the last second, used for ups and fps
62  */
63 int target_UPS = 250;
64 long int last_Block_Update;
65 float update_Sum = 0;
66
67 int ups, fps;
68 int update_Count, draw_Count;
69 long int last_Second;
70
71
72 /// ***** MAIN Method *****
73 int main()
74 {
75     init();
76     run();
77     clean();
78     return 0;
79 }
80
81 /// ***** Initializers/Cleaners *****
82
83 void init()
84 {
85     installSignal();
86
87     graphics::init();
88
89     game::init();
90
91     input::init();
92
93 #ifdef DEBUGGING
94     cout << "Initialization Complete" << endl;
95 #endif
96 }
97
98 void clean()
99 {
100 #ifdef DEBUGGING
101     cout << "Cleaning up" << endl;
102 #endif
103
104     input::clean();
105
106     game::clean();
107
108     graphics::clean();
109 }
110
111 /// ***** Private Methods *****
112
113 void run()
114 {
115     is_Running = true;
116     last_Block_Update = tickCountMicro();
117     last_Second = tickCountMicro();
118
119     while(is_Running)
120     {
121         blockUpdate();
122         updateFPSCounters();
123         draw();
124     }
125 }
126
127 void blockUpdate()
128 {
129     long int start = tickCountMicro();
130
131     // Calculate the updates that should be run for the next draw
132     update_Sum += (start - last_Block_Update) / (1000000 / (float)target_UPS);
133
134     // insures the float to int cast is done once.
135     int iupdate_sum = (int)update_Sum;
136
137     // TODO the main run loop needs to be tested and pruned
138     if (iupdate_sum > 0)
139     {
140         // Calculate a time step that spreads the updates out as much as possible
141         // used because really quick updates are nearly wasted
142         float time_step = ((float)(start - last_Block_Update)) / iupdate_sum;
143
144         // run the updates
145         for (int i = 1; i <= iupdate_sum; i++)
146         {
147             handleInput();
148             update(time_step*i / 1000);
149         }
150         // remove the updates that where run from the sum
151         update_Sum -= iupdate_sum;
152         last_Block_Update = tickCountMicro();
153     }
154 }
155
156 void updateFPSCounters()
157 {
158     // Check if a second has passed to recalculate UPS and FPS
159     if (tickCountMicro() - last_Second >= 1000000)
160     {
161         ups = update_Count;
162         fps = draw_Count;
163         update_Count = 0;
164         draw_Count = 0;
165
166         last_Second = tickCountMicro();
167
168 #ifdef FPSUPS
169         cout << "ups:\t" << ups << endl;
170         cout << "fps:\t" << fps << endl;
171 #endif
172     }
173 }
174
175 void handleInput()
176 {
177     input::update();
178
179     game::input();
180
181     if(input::wasReleased(SDLK_ESCAPE))
182         is_Running = false;
183 }
184
185 void update(float time_step)
186 {
187     update_Count++;
188
189     game::update(time_step);
190 }
191
192 void draw()
193 {
194     draw_Count++;
195
196     game::draw();
197
198     SDL_GL_SwapBuffers();
199
200     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
201 }