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