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