]>
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"
38 #include "Dispatcher.hh"
41 #include "Exception.hh"
44 #include "Settings.hh"
56 Impl(int argc
, char* argv
[], const std::string
& name
,
57 const std::string
& iconFile
, const std::string
& configFile
,
63 #if defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__) || defined(__WINDOWS__)
64 if (SDL_Init(SDL_INIT_VIDEO
| SDL_INIT_TIMER
) != 0)
66 if (SDL_Init(SDL_INIT_VIDEO
| SDL_INIT_EVENTTHREAD
) != 0)
69 const char* error
= SDL_GetError();
70 logError("sdl is complaining: %s", error
);
71 throw Exception(ErrorCode::SDL_INIT
, error
);
75 const char* error
= FE_GetError();
76 logError("fast events error: %s", error
);
77 throw Exception(ErrorCode::FASTEVENTS_INIT
, error
);
79 alutInit(&argc
, argv
);
81 Settings
& settings
= Settings::getInstance();
82 settings
.loadFromFile(configFile
);
83 settings
.parseArgs(argc
, argv
);
86 if (settings
.get("rngseed", randomSeed
)) setSeed(randomSeed
);
89 Scalar timestep
= 80.0;
90 settings
.get("timestep", timestep
);
91 mTimestep
= 1.0 / timestep
;
94 settings
.get("maxfps", maxFps
);
95 mDrawRate
= 1.0 / maxFps
;
97 settings
.get("printfps", mPrintFps
);
99 mVideo
= Video::alloc(name
, iconFile
);
100 mVideo
->makeActive();
105 // the video object must be destroyed before we can shutdown SDL
115 * The main loop. This just calls dispatchEvents(), update(), and draw()
116 * over and over again. The timing of the update and draw are decoupled.
117 * The actual frame rate is also calculated here. This function will return
118 * the exit code used to stop the loop.
123 Scalar ticksNow
= Timer::getTicks();
125 Scalar nextStep
= ticksNow
;
126 Scalar nextDraw
= ticksNow
;
127 Scalar nextFpsUpdate
= ticksNow
+ 1.0;
129 Scalar totalTime
= 0.0;
130 Scalar deltaTime
= 0.0;
131 Scalar accumulator
= mTimestep
;
138 Scalar newTicks
= Timer::getTicks();
139 deltaTime
= newTicks
- ticksNow
;
142 if (deltaTime
>= 0.25) deltaTime
= 0.25;
143 accumulator
+= deltaTime
;
145 Timer::fireIfExpired(ticksNow
);
147 while (accumulator
>= mTimestep
)
150 update(totalTime
, mTimestep
);
152 totalTime
+= mTimestep
;
153 accumulator
-= mTimestep
;
155 nextStep
+= mTimestep
;
157 if (ticksNow
>= nextStep
)
159 nextStep
= ticksNow
+ mTimestep
;
162 if (ticksNow
>= nextDraw
)
166 if (ticksNow
>= nextFpsUpdate
) // determine the actual fps
171 nextFpsUpdate
+= 1.0;
172 if (ticksNow
>= nextFpsUpdate
)
174 nextFpsUpdate
= ticksNow
+ 1.0;
179 logInfo("%d fps", mFps
);
183 draw(accumulator
/ mTimestep
);
186 nextDraw
+= mDrawRate
;
187 if (ticksNow
>= nextDraw
)
189 // we missed some scheduled draws, so reset the schedule
190 nextDraw
= ticksNow
+ mDrawRate
;
194 // be a good citizen and give back what you don't need
195 Timer::sleep(std::min(std::min(nextStep
, nextDraw
),
196 Timer::getNextFire()), true);
198 while (!mStack
.empty());
201 void dispatchEvents()
205 while (FE_PollEvent(&event
) == 1)
210 if (event
.key
.keysym
.sym
== SDLK_ESCAPE
&&
211 (SDL_GetModState() & KMOD_CTRL
) )
218 case SDL_VIDEORESIZE
:
219 mVideo
->resize(event
.resize
.w
, event
.resize
.h
);
228 void update(Scalar t
, Scalar dt
)
230 for (mStackIt
= mStack
.begin(); mStackIt
!= mStack
.end(); ++mStackIt
)
232 (*mStackIt
)->update(t
, dt
);
236 void draw(Scalar alpha
)
238 // FIXME - this will crash if the layer being drawn pops itself
239 std::list
<LayerP
>::reverse_iterator it
;
240 for (it
= mStack
.rbegin(); it
!= mStack
.rend(); ++it
)
246 void handleEvent(const Event
& event
)
248 for (mStackIt
= mStack
.begin(); mStackIt
!= mStack
.end(); ++mStackIt
)
250 if ((*mStackIt
)->handleEvent(event
)) break;
255 void push(LayerP layer
)
257 ASSERT(layer
&& "cannot push null layer");
258 mStack
.push_front(layer
);
259 logInfo(" push: %d", mStack
.size());
260 layer
->pushed(mInterface
);
266 if (mStack
.begin() == mStackIt
) fixIt
= true;
268 LayerP popped
= mStack
.front();
270 logInfo(" pop: %d", mStack
.size());
271 popped
->popped(mInterface
);
273 if (fixIt
) mStackIt
= --mStack
.begin();
278 LayerP
pop(Layer
* layer
)
282 std::list
<LayerP
> popped
;
284 std::list
<LayerP
>::iterator it
;
285 for (it
= mStack
.begin(); it
!= mStack
.end(); ++it
)
287 popped
.push_back(*it
);
289 if (it
== mStackIt
) fixIt
= true;
291 if ((*it
).get() == layer
)
294 mStack
.erase(mStack
.begin(), it
);
296 for (it
= popped
.begin(); it
!= popped
.end(); ++it
)
298 (*it
)->popped(mInterface
);
301 if (fixIt
) mStackIt
= --mStack
.begin();
303 return popped
.back();
313 mStackIt
= mStack
.begin();
314 logInfo("clear: %d", mStack
.size());
322 std::list
<LayerP
> mStack
;
323 std::list
<LayerP
>::iterator mStackIt
;
333 static Engine
* instance
= 0;
335 Engine::Engine(int argc
, char* argv
[], const std::string
& name
,
336 const std::string
& iconFile
, const std::string
& configFile
) :
337 mImpl(new Engine::Impl(argc
, argv
, name
, iconFile
, configFile
, *this))
343 Engine
& Engine::getInstance()
345 ASSERT(instance
&& "dereferencing null pointer");
347 // TODO this has not been completely thought out
348 //static Engine engine;
358 void Engine::setTimestep(Scalar ts
)
360 mImpl
->mTimestep
= ts
;
363 Scalar
Engine::getTimestep() const
365 return mImpl
->mTimestep
;
368 void Engine::setMaxFrameRate(long maxFps
)
370 mImpl
->mDrawRate
= 1.0 / Scalar(maxFps
);
373 long Engine::getMaxFrameRate() const
375 return long(1.0 / mImpl
->mDrawRate
);
379 Video
& Engine::getVideo() const
381 return *mImpl
->mVideo
;
384 long Engine::getFrameRate() const
390 void Engine::push(LayerP layer
)
402 LayerP
Engine::pop(Layer
* layer
)
405 return mImpl
->pop(layer
);
417 /** vim: set ts=4 sw=4 tw=80: *************************************************/
This page took 0.055125 seconds and 4 git commands to generate.