]>
Dogcows Code - chaz/yoink/blob - src/Moof/Engine.cc
2 /*******************************************************************************
4 Copyright (c) 2009, Charles McGarvey
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
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.
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.
27 *******************************************************************************/
30 #include <cstdlib> // exit
35 #include "fastevents.h"
40 #include "Exception.hh"
44 #include "Settings.hh"
55 Impl(Engine
& engine
) :
60 // first, initialize the libraries
62 #if defined(_WIN32) || defined(__WIN32__)
63 if (SDL_Init(SDL_INIT_VIDEO
| SDL_INIT_TIMER
) != 0)
65 if (SDL_Init(SDL_INIT_VIDEO
| SDL_INIT_EVENTTHREAD
) != 0)
68 const char* error
= SDL_GetError();
69 throw Exception(ErrorCode::SDL_INIT
, error
);
73 const char* error
= FE_GetError();
74 throw Exception(ErrorCode::FASTEVENTS_INIT
, error
);
77 char name
[] = "hello";
78 alutInit(&argc
, (char**)&name
);
80 // now load the settings the engine needs
82 Settings
& settings
= Settings::getInstance();
85 if (settings
.get("rngseed", randomSeed
)) setSeed(randomSeed
);
88 Scalar timestep
= 80.0;
89 settings
.get("timestep", timestep
);
90 mTimestep
= 1.0 / timestep
;
93 settings
.get("maxfps", maxFps
);
94 mMaxFps
= 1.0 / maxFps
;
97 settings
.get("printfps", mPrintFps
);
102 // the video object must be destroyed before we can shutdown SDL
112 * The main loop. This just calls dispatchEvents(), update(), and draw()
113 * over and over again. The timing of the update and draw are decoupled.
114 * The actual frame rate is also calculated here. This function will return
115 * the exit code used to stop the loop.
120 Scalar ticksNow
= Timer::getTicks();
122 Scalar nextStep
= ticksNow
;
123 Scalar nextDraw
= ticksNow
;
124 Scalar nextFpsUpdate
= ticksNow
+ 1.0;
126 Scalar totalTime
= 0.0;
127 Scalar deltaTime
= 0.0;
128 Scalar accumulator
= mTimestep
;
135 Scalar newTicks
= Timer::getTicks();
136 deltaTime
= newTicks
- ticksNow
;
139 // don't slow the animation until 4Hz, which is unplayable anyway
140 if (deltaTime
>= 0.25) deltaTime
= 0.25;
141 accumulator
+= deltaTime
;
143 Timer::fireIfExpired(ticksNow
);
146 while (accumulator
>= mTimestep
)
148 update(totalTime
, mTimestep
);
150 totalTime
+= mTimestep
;
151 accumulator
-= mTimestep
;
153 nextStep
+= mTimestep
;
155 if (ticksNow
>= nextStep
)
157 nextStep
= ticksNow
+ mTimestep
;
160 if (ticksNow
>= nextDraw
)
164 if (ticksNow
>= nextFpsUpdate
) // determine the actual fps
169 nextFpsUpdate
+= 1.0;
170 if (ticksNow
>= nextFpsUpdate
)
172 nextFpsUpdate
= ticksNow
+ 1.0;
177 logInfo("%d fps", mFps
);
181 draw(accumulator
/ mTimestep
);
185 if (ticksNow
>= nextDraw
)
187 // we missed some scheduled draws, so reset the schedule
188 nextDraw
= ticksNow
+ mMaxFps
;
192 // be a good citizen and give back what you don't need
193 Timer::sleep(std::min(std::min(nextStep
, nextDraw
),
194 Timer::getNextFire()), Timer::ACTUAL
);
196 while (!mStack
.empty());
199 void dispatchEvents()
203 while (FE_PollEvent(&event
) == 1)
208 if (event
.key
.keysym
.sym
== SDLK_ESCAPE
&&
209 (SDL_GetModState() & KMOD_CTRL
) )
212 logWarning("escape forced");
217 case SDL_VIDEORESIZE
:
218 mVideo
->resize(event
.resize
.w
, event
.resize
.h
);
227 void update(Scalar t
, Scalar dt
)
229 for (mStackIt
= mStack
.begin(); mStackIt
!= mStack
.end(); ++mStackIt
)
231 (*mStackIt
)->update(mInterface
, t
, dt
);
235 void draw(Scalar alpha
)
237 // FIXME - this will crash if the layer being drawn pops itself
238 std::list
<LayerP
>::reverse_iterator it
;
239 for (it
= mStack
.rbegin(); it
!= mStack
.rend(); ++it
)
241 (*it
)->draw(mInterface
, alpha
);
245 void handleEvent(const Event
& event
)
247 for (mStackIt
= mStack
.begin(); mStackIt
!= mStack
.end(); ++mStackIt
)
249 if ((*mStackIt
)->handleEvent(mInterface
, event
)) break;
254 void push(LayerP layer
)
256 ASSERT(layer
&& "cannot push null layer");
257 mStack
.push_front(layer
);
258 logDebug("stack: %d [pushed %X]", mStack
.size(), layer
.get());
259 layer
->pushed(mInterface
);
265 if (mStack
.begin() == mStackIt
) fixIt
= true;
267 LayerP layer
= mStack
.front();
269 logDebug("stack: %d [popped %X]", mStack
.size(), layer
.get());
270 layer
->popped(mInterface
);
272 if (fixIt
) mStackIt
= --mStack
.begin();
277 LayerP
pop(Layer
* layer
)
281 std::list
<LayerP
> layers
;
283 std::list
<LayerP
>::iterator it
;
284 for (it
= mStack
.begin(); it
!= mStack
.end(); ++it
)
286 layers
.push_back(*it
);
288 if (it
== mStackIt
) fixIt
= true;
290 if ((*it
).get() == layer
)
293 mStack
.erase(mStack
.begin(), it
);
295 for (it
= layers
.begin(); it
!= layers
.end(); ++it
)
297 (*it
)->popped(mInterface
);
298 logDebug("stack: %d [popped %X]", mStack
.size(), (*it
).get());
301 if (fixIt
) mStackIt
= --mStack
.begin();
303 return layers
.back();
313 mStackIt
= mStack
.begin();
314 logDebug("stack: 0 [cleared]");
320 if (mMaxFps
< mTimestep
)
322 logWarning("capping maximum fps to timestep (%f)", mTimestep
);
332 std::list
<LayerP
> mStack
;
333 std::list
<LayerP
>::iterator mStackIt
;
345 mImpl(new Engine::Impl(*this)) {}
347 Engine
& Engine::getInstance()
349 static Engine engine
;
354 void Engine::setVideo(VideoP video
)
357 mImpl
->mVideo
= video
;
360 VideoP
Engine::getVideo() const
362 return mImpl
->mVideo
;
366 void Engine::setTimestep(int ts
)
368 mImpl
->mTimestep
= 1.0 / Scalar(ts
);
372 int Engine::getTimestep() const
374 return int(1.0 / mImpl
->mTimestep
);
378 void Engine::setMaxFps(int maxFps
)
380 mImpl
->mMaxFps
= 1.0 / Scalar(maxFps
);
384 int Engine::getMaxFps() const
386 return int(1.0 / mImpl
->mMaxFps
);
390 int Engine::getFps() const
396 void Engine::push(LayerP layer
)
408 LayerP
Engine::pop(Layer
* layer
)
411 return mImpl
->pop(layer
);
420 int Engine::getSize() const
422 return mImpl
->mStack
.size();
433 Dispatch::Handler
Engine::addHandler(const std::string
& event
,
434 const Dispatch::Function
& callback
)
436 return mImpl
->mDispatch
.addHandler(event
, callback
);
439 Dispatch::Handler
Engine::addHandler(const std::string
& event
,
440 const Dispatch::Function
& callback
, Dispatch::Handler handler
)
442 return mImpl
->mDispatch
.addHandler(event
, callback
, handler
);
445 void Engine::dispatch(const std::string
& event
,
446 const Dispatch::Message
* message
)
448 mImpl
->mDispatch
.dispatch(event
, message
);
454 /** vim: set ts=4 sw=4 tw=80: *************************************************/
This page took 0.058554 seconds and 5 git commands to generate.