]> Dogcows Code - chaz/yoink/blob - src/Moof/Engine.cc
fixed up video and texture handling
[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
36 #include "Dispatcher.hh"
37 #include "Engine.hh"
38 #include "Random.hh"
39 #include "Settings.hh"
40 #include "Timer.hh"
41 #include "Video.hh"
42
43
44 namespace Mf {
45
46
47 class Engine::EngineImpl
48 {
49 public:
50 EngineImpl(int argc, char* argv[], const std::string& configFile,
51 const std::string& name, const std::string& iconFile,
52 Engine* outer) :
53 interface(outer),
54 settings(argc, argv)
55 {
56 if (SDL_Init(SDL_INIT_EVERYTHING | SDL_INIT_EVENTTHREAD) != 0)
57 {
58 throw Exception(SDL_GetError());
59 }
60 if (FE_Init() != 0)
61 {
62 throw Exception(FE_GetError());
63 }
64
65 settings.loadFromFile(configFile);
66
67 long randomSeed;
68 if (settings.get("engine.rngseed", randomSeed))
69 {
70 setSeed(randomSeed);
71 }
72 else
73 {
74 setSeed();
75 }
76
77 double ts = 0.01;
78 settings.get("engine.timestep", ts);
79 timestep = Scalar(ts);
80
81 long maxFps = 40;
82 settings.getNumber("video.maxfps", maxFps);
83 drawRate = 1.0 / Scalar(maxFps);
84
85 printFps = false;
86 settings.get("video.printfps", printFps);
87
88 video = VideoPtr(new Video(name, iconFile));
89 video->makeActive();
90 }
91
92 ~EngineImpl()
93 {
94 // the video object must be destroyed before we can shutdown SDL
95 video.reset();
96
97 FE_Quit();
98 SDL_Quit();
99 }
100
101
102 /**
103 * The main loop. This just calls dispatchEvents(), update(), and draw()
104 * over and over again. The timing of the update and draw are decoupled.
105 * The actual frame rate is also calculated here. This function will return
106 * with a value of 0 if the member variable running becomes true.
107 */
108
109 int run()
110 {
111 Scalar ticksNow = getTicks();
112
113 Scalar nextStep = ticksNow;
114 Scalar nextDraw = ticksNow;
115 Scalar nextFpsUpdate = ticksNow + 1.0;
116
117 Scalar totalTime = 0.0;
118 Scalar deltaTime = 0.0;
119 Scalar accumulator = timestep;
120
121 fps = 0;
122 int frameAccum = 0;
123
124 running = true;
125 do
126 {
127 Scalar newTicks = getTicks();
128 deltaTime = newTicks - ticksNow;
129 ticksNow = newTicks;
130
131 if (deltaTime >= 0.25) deltaTime = 0.25;
132 accumulator += deltaTime;
133
134 while (accumulator >= timestep)
135 {
136 dispatchEvents();
137 interface->update(totalTime, timestep);
138
139 totalTime += timestep;
140 accumulator -= timestep;
141
142 nextStep += timestep;
143 }
144
145 if (ticksNow >= nextDraw)
146 {
147 frameAccum++;
148
149 if (ticksNow >= nextFpsUpdate) // determine the actual fps
150 {
151 fps = frameAccum;
152 frameAccum = 0;
153
154 nextFpsUpdate += 1.0;
155 if (ticksNow >= nextFpsUpdate)
156 {
157 nextFpsUpdate = ticksNow + 1.0;
158 }
159
160 if (printFps)
161 {
162 std::cout << "FPS: " << fps << std::endl;
163 }
164 }
165
166 interface->draw(accumulator / timestep);
167 video->swap();
168
169 nextDraw += drawRate;
170 if (ticksNow >= nextDraw)
171 {
172 // we missed some scheduled draws, so reset the schedule
173 nextDraw = ticksNow + drawRate;
174 }
175 }
176
177 // be a good citizen and give back what you don't need
178 sleep(std::min(nextStep, nextDraw), true);
179 }
180 while (running);
181
182 return 0;
183 }
184
185
186 void dispatchEvents()
187 {
188 SDL_Event event;
189
190 while (FE_PollEvent(&event) == 1)
191 {
192 switch (event.type)
193 {
194 case SDL_KEYDOWN:
195 if (event.key.keysym.sym == SDLK_ESCAPE &&
196 (SDL_GetModState() & KMOD_CTRL) )
197 {
198 exit(0);
199 }
200 break;
201
202 case SDL_VIDEORESIZE:
203 video->resize(event.resize.w, event.resize.h);
204 break;
205 }
206
207 interface->handleEvent(event);
208 }
209 }
210
211
212 Engine* interface;
213
214 Settings settings;
215 Dispatcher dispatcher;
216 VideoPtr video;
217
218 bool running;
219
220 Scalar timestep;
221 Scalar drawRate;
222
223 long fps;
224 bool printFps;
225 };
226
227
228 Engine::Engine(int argc, char* argv[], const std::string& configFile,
229 const std::string& name, const std::string& iconFile) :
230 impl_(new Engine::EngineImpl(argc, argv, configFile, name, iconFile, this))
231 {}
232
233 Engine::~Engine() {}
234
235
236 int Engine::run()
237 {
238 return impl_->run();
239 }
240
241 void Engine::stop()
242 {
243 impl_->running = false;
244 }
245
246
247 void Engine::setTimestep(Scalar ts)
248 {
249 impl_->timestep = ts;
250 }
251
252 Scalar Engine::getTimestep()
253 {
254 return impl_->timestep;
255 }
256
257 void Engine::setMaxFrameRate(long maxFps)
258 {
259 impl_->drawRate = 1.0 / Scalar(maxFps);
260 }
261
262 long Engine::getMaxFrameRate()
263 {
264 return long(1.0 / impl_->drawRate);
265 }
266
267
268 Video& Engine::getVideo()
269 {
270 return *impl_->video;
271 }
272
273 long Engine::getFrameRate()
274 {
275 return impl_->fps;
276 }
277
278
279 void Engine::update(Scalar t, Scalar dt) {}
280 void Engine::draw(Scalar alpha) {}
281 void Engine::handleEvent(const Event& event) {}
282
283
284 } // namespace Mf
285
286 /** vim: set ts=4 sw=4 tw=80: *************************************************/
287
This page took 0.041214 seconds and 4 git commands to generate.