]> Dogcows Code - chaz/yoink/blob - src/Moof/Engine.cc
initial port to win32
[chaz/yoink] / src / Moof / Engine.cc
1
2 /*******************************************************************************
3
4 Copyright (c) 2009, Charles McGarvey
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9
10 * Redistributions of source code must retain the above copyright notice,
11 this list of conditions and the following disclaimer.
12 * Redistributions in binary form must reproduce the above copyright notice,
13 this list of conditions and the following disclaimer in the documentation
14 and/or other materials provided with the distribution.
15
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27 *******************************************************************************/
28
29 #include <cstdlib> // exit
30 #include <iostream>
31 #include <string>
32
33 #include <SDL/SDL.h>
34 #include "fastevents.h"
35 #include <SDL/SDL_sound.h>
36 #include <AL/alut.h>
37
38 #include "Engine.hh"
39 #include "Random.hh"
40 #include "Settings.hh"
41 #include "Timer.hh"
42 #include "Video.hh"
43
44
45 namespace Mf {
46
47
48 class Engine::Impl
49 {
50 public:
51 Impl(int argc, char* argv[], const std::string& configFile,
52 const std::string& name, const std::string& iconFile,
53 Engine* outer) :
54 interface(outer)
55 {
56 #if defined(_WIN32) || defined (_WIN64) || defined(__WIN32__)
57 if (SDL_Init(SDL_INIT_EVERYTHING) != 0)
58 #else
59 if (SDL_Init(SDL_INIT_EVERYTHING | SDL_INIT_EVENTTHREAD) != 0)
60 #endif
61 {
62 std::cerr << "sdl is complaining: " << SDL_GetError() << std::endl;
63 throw Exception(Exception::SDL_ERROR);
64 }
65 if (FE_Init() != 0)
66 {
67 std::cerr << "fast events error: " << FE_GetError() << std::endl;
68 throw Exception(Exception::SDL_ERROR);
69 }
70 if (Sound_Init() == 0)
71 {
72 std::cerr << "sound initialization failed: " << Sound_GetError()
73 << std::endl;
74 throw Exception(Exception::SDL_ERROR);
75 }
76 alutInit(&argc, argv);
77
78 Settings& settings = Settings::getInstance();
79 settings.parseArgs(argc, argv);
80 settings.loadFromFile(configFile);
81
82 long randomSeed;
83 if (settings.get("engine.rngseed", randomSeed)) setSeed(randomSeed);
84 else setSeed();
85
86 double ts = 0.01;
87 settings.get("engine.timestep", ts);
88 timestep = Scalar(ts);
89
90 long maxFps = 40;
91 settings.getNumber("video.maxfps", maxFps);
92 drawRate = 1.0 / Scalar(maxFps);
93
94 printFps = false;
95 settings.get("video.printfps", printFps);
96
97 video = Video::alloc(name, iconFile);
98 video->makeActive();
99 }
100
101 ~Impl()
102 {
103 // the video object must be destroyed before we can shutdown SDL
104 video.reset();
105
106 alutExit();
107 Sound_Quit();
108 FE_Quit();
109 SDL_Quit();
110 }
111
112
113 /**
114 * The main loop. This just calls dispatchEvents(), update(), and draw()
115 * over and over again. The timing of the update and draw are decoupled.
116 * The actual frame rate is also calculated here. This function will return
117 * the exit code used to stop the loop.
118 */
119
120 int run()
121 {
122 Scalar ticksNow = getTicks();
123
124 Scalar nextStep = ticksNow;
125 Scalar nextDraw = ticksNow;
126 Scalar nextFpsUpdate = ticksNow + 1.0;
127
128 Scalar totalTime = 0.0;
129 Scalar deltaTime = 0.0;
130 Scalar accumulator = timestep;
131
132 fps = 0;
133 int frameAccum = 0;
134
135 running = true;
136 do
137 {
138 Scalar newTicks = getTicks();
139 deltaTime = newTicks - ticksNow;
140 ticksNow = newTicks;
141
142 if (deltaTime >= 0.25) deltaTime = 0.25;
143 accumulator += deltaTime;
144
145 while (accumulator >= timestep)
146 {
147 dispatchEvents();
148 interface->update(totalTime, timestep);
149
150 totalTime += timestep;
151 accumulator -= timestep;
152
153 nextStep += timestep;
154 }
155 if (ticksNow >= nextStep)
156 {
157 nextStep = ticksNow + timestep;
158 }
159
160 if (ticksNow >= nextDraw)
161 {
162 frameAccum++;
163
164 if (ticksNow >= nextFpsUpdate) // determine the actual fps
165 {
166 fps = frameAccum;
167 frameAccum = 0;
168
169 nextFpsUpdate += 1.0;
170 if (ticksNow >= nextFpsUpdate)
171 {
172 nextFpsUpdate = ticksNow + 1.0;
173 }
174
175 if (printFps)
176 {
177 std::cout << "FPS: " << fps << std::endl;
178 }
179 }
180
181 interface->draw(accumulator / timestep);
182 video->swap();
183
184 nextDraw += drawRate;
185 if (ticksNow >= nextDraw)
186 {
187 // we missed some scheduled draws, so reset the schedule
188 nextDraw = ticksNow + drawRate;
189 }
190 }
191
192 // be a good citizen and give back what you don't need
193 sleep(std::min(nextStep, nextDraw), true);
194 }
195 while (running);
196
197 return exitCode;
198 }
199
200
201 void dispatchEvents()
202 {
203 SDL_Event event;
204
205 while (FE_PollEvent(&event) == 1)
206 {
207 switch (event.type)
208 {
209 case SDL_KEYDOWN:
210 if (event.key.keysym.sym == SDLK_ESCAPE &&
211 (SDL_GetModState() & KMOD_CTRL) )
212 {
213 exit(0);
214 }
215 break;
216
217 case SDL_VIDEORESIZE:
218 video->resize(event.resize.w, event.resize.h);
219 break;
220 }
221
222 interface->handleEvent(event);
223 }
224 }
225
226
227 Engine* interface;
228
229 VideoP video;
230
231 bool running;
232 int exitCode;
233
234 Scalar timestep;
235 Scalar drawRate;
236
237 long fps;
238 bool printFps;
239 };
240
241
242 Engine::Engine(int argc, char* argv[], const std::string& configFile,
243 const std::string& name, const std::string& iconFile) :
244 impl_(new Engine::Impl(argc, argv, configFile, name, iconFile, this)) {}
245
246 Engine::~Engine() {}
247
248
249 int Engine::run()
250 {
251 return impl_->run();
252 }
253
254 void Engine::stop(int exitCode)
255 {
256 impl_->running = false;
257 impl_->exitCode = exitCode;
258 }
259
260
261 void Engine::setTimestep(Scalar ts)
262 {
263 impl_->timestep = ts;
264 }
265
266 Scalar Engine::getTimestep()
267 {
268 return impl_->timestep;
269 }
270
271 void Engine::setMaxFrameRate(long maxFps)
272 {
273 impl_->drawRate = 1.0 / Scalar(maxFps);
274 }
275
276 long Engine::getMaxFrameRate()
277 {
278 return long(1.0 / impl_->drawRate);
279 }
280
281
282 Video& Engine::getVideo()
283 {
284 return *impl_->video;
285 }
286
287 long Engine::getFrameRate()
288 {
289 return impl_->fps;
290 }
291
292
293 void Engine::update(Scalar t, Scalar dt) {}
294 void Engine::draw(Scalar alpha) {}
295 void Engine::handleEvent(const Event& event) {}
296
297
298 } // namespace Mf
299
300 /** vim: set ts=4 sw=4 tw=80: *************************************************/
301
This page took 0.045785 seconds and 5 git commands to generate.