X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fyoink;a=blobdiff_plain;f=src%2FMoof%2FEngine.cc;h=ccf2347c175e392af6baaa1b7748b44502b6dfa8;hp=53fca73e9e883cfab1d18aced70cd125391f26d1;hb=a31d65a998121df0651c57bfb68782e2a07d2e2f;hpb=72d4af22710317acffab861421c4364b1780b6fe diff --git a/src/Moof/Engine.cc b/src/Moof/Engine.cc index 53fca73..ccf2347 100644 --- a/src/Moof/Engine.cc +++ b/src/Moof/Engine.cc @@ -26,15 +26,19 @@ *******************************************************************************/ +#include #include // exit -#include +#include #include #include #include "fastevents.h" +#include #include "Dispatcher.hh" #include "Engine.hh" +#include "Event.hh" +#include "Log.hh" #include "Random.hh" #include "Settings.hh" #include "Timer.hh" @@ -44,56 +48,61 @@ namespace Mf { -class Engine::EngineImpl +class Engine::Impl { public: - EngineImpl(int argc, char* argv[], const std::string& configFile, - const std::string& name, const std::string& iconFile, - Engine* outer) : - interface(outer), - settings(argc, argv) + + Impl(int argc, char* argv[], const std::string& name, + const std::string& iconFile, const std::string& configFile, + Engine& engine) : + mInterface(engine), + mTimestep(0.01), + mPrintFps(false) { - if (SDL_Init(SDL_INIT_EVERYTHING | SDL_INIT_EVENTTHREAD) != 0) +#if defined(_WIN32) || defined (_WIN64) || defined(__WIN32__) + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) != 0) +#else + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTTHREAD) != 0) +#endif { - throw Exception(SDL_GetError()); + logError("sdl is complaining: %s", SDL_GetError()); + throw Exception(Exception::SDL_ERROR); } if (FE_Init() != 0) { - throw Exception(FE_GetError()); + logError("fast events error: %s", FE_GetError()); + throw Exception(Exception::SDL_ERROR); } + alutInit(&argc, argv); + Settings& settings = Settings::getInstance(); settings.loadFromFile(configFile); + settings.parseArgs(argc, argv); long randomSeed; - if (settings.get("engine.rngseed", randomSeed)) - { - setSeed(randomSeed); - } - else - { - setSeed(); - } + if (settings.get("rngseed", randomSeed)) setSeed(randomSeed); + else setSeed(); - double ts = 0.01; - settings.get("engine.timestep", ts); - timestep = Scalar(ts); + Scalar timestep = 80.0; + settings.get("timestep", timestep); + mTimestep = 1.0 / timestep; - long maxFps = 40; - settings.getNumber("video.maxfps", maxFps); - drawRate = 1.0 / Scalar(maxFps); + Scalar maxFps = 40.0; + settings.get("maxfps", maxFps); + mDrawRate = 1.0 / maxFps; - printFps = false; - settings.get("video.printfps", printFps); + settings.get("printfps", mPrintFps); - video = VideoPtr(new Video(name, iconFile)); - video->makeActive(); + mVideo = Video::alloc(name, iconFile); + mVideo->makeActive(); } - ~EngineImpl() + ~Impl() { // the video object must be destroyed before we can shutdown SDL - video.reset(); + mVideo.reset(); + alutExit(); FE_Quit(); SDL_Quit(); } @@ -106,9 +115,9 @@ public: * the exit code used to stop the loop. */ - int run() + void run() { - Scalar ticksNow = getTicks(); + Scalar ticksNow = Timer::getTicks(); Scalar nextStep = ticksNow; Scalar nextDraw = ticksNow; @@ -116,34 +125,35 @@ public: Scalar totalTime = 0.0; Scalar deltaTime = 0.0; - Scalar accumulator = timestep; + Scalar accumulator = mTimestep; - fps = 0; + mFps = 0; int frameAccum = 0; - running = true; do { - Scalar newTicks = getTicks(); + Scalar newTicks = Timer::getTicks(); deltaTime = newTicks - ticksNow; ticksNow = newTicks; if (deltaTime >= 0.25) deltaTime = 0.25; accumulator += deltaTime; - while (accumulator >= timestep) + Timer::fireIfExpired(ticksNow); + + while (accumulator >= mTimestep) { dispatchEvents(); - interface->update(totalTime, timestep); + update(totalTime, mTimestep); - totalTime += timestep; - accumulator -= timestep; + totalTime += mTimestep; + accumulator -= mTimestep; - nextStep += timestep; + nextStep += mTimestep; } if (ticksNow >= nextStep) { - nextStep = ticksNow + timestep; + nextStep = ticksNow + mTimestep; } if (ticksNow >= nextDraw) @@ -152,7 +162,7 @@ public: if (ticksNow >= nextFpsUpdate) // determine the actual fps { - fps = frameAccum; + mFps = frameAccum; frameAccum = 0; nextFpsUpdate += 1.0; @@ -161,32 +171,30 @@ public: nextFpsUpdate = ticksNow + 1.0; } - if (printFps) + if (mPrintFps) { - std::cout << "FPS: " << fps << std::endl; + logInfo("%d fps", mFps); } } - interface->draw(accumulator / timestep); - video->swap(); + draw(accumulator / mTimestep); + mVideo->swap(); - nextDraw += drawRate; + nextDraw += mDrawRate; if (ticksNow >= nextDraw) { // we missed some scheduled draws, so reset the schedule - nextDraw = ticksNow + drawRate; + nextDraw = ticksNow + mDrawRate; } } // be a good citizen and give back what you don't need - sleep(std::min(nextStep, nextDraw), true); + Timer::sleep(std::min(std::min(nextStep, nextDraw), + Timer::getNextFire()), true); } - while (running); - - return exitCode; + while (!mStack.empty()); } - void dispatchEvents() { SDL_Event event; @@ -199,92 +207,206 @@ public: if (event.key.keysym.sym == SDLK_ESCAPE && (SDL_GetModState() & KMOD_CTRL) ) { - exit(0); + // emergency escape + exit(0); } break; case SDL_VIDEORESIZE: - video->resize(event.resize.w, event.resize.h); + mVideo->resize(event.resize.w, event.resize.h); break; } - interface->handleEvent(event); + handleEvent(event); } } - Engine* interface; + void update(Scalar t, Scalar dt) + { + for (mStackIt = mStack.begin(); mStackIt != mStack.end(); ++mStackIt) + { + (*mStackIt)->update(t, dt); + } + } - Settings settings; - Dispatcher dispatcher; - VideoPtr video; + void draw(Scalar alpha) + { + // FIXME - this will crash if the layer being drawn pops itself + std::list::reverse_iterator it; + for (it = mStack.rbegin(); it != mStack.rend(); ++it) + { + (*it)->draw(alpha); + } + } - bool running; - int exitCode; + void handleEvent(const Event& event) + { + for (mStackIt = mStack.begin(); mStackIt != mStack.end(); ++mStackIt) + { + if ((*mStackIt)->handleEvent(event)) break; + } + } - Scalar timestep; - Scalar drawRate; - long fps; - bool printFps; -}; + void push(LayerP layer) + { + ASSERT(layer && "cannot push null layer"); + mStack.push_front(layer); + logInfo(" push: %d", mStack.size()); + layer->pushed(mInterface); + } + LayerP pop() + { + bool fixIt = false; + if (mStack.begin() == mStackIt) fixIt = true; + + LayerP popped = mStack.front(); + mStack.pop_front(); + logInfo(" pop: %d", mStack.size()); + popped->popped(mInterface); -Engine::Engine(int argc, char* argv[], const std::string& configFile, - const std::string& name, const std::string& iconFile) : - impl_(new Engine::EngineImpl(argc, argv, configFile, name, iconFile, this)) -{} + if (fixIt) mStackIt = --mStack.begin(); -Engine::~Engine() {} + return popped; + } + LayerP pop(Layer* layer) + { + bool fixIt = false; -int Engine::run() + std::list popped; + + std::list::iterator it; + for (it = mStack.begin(); it != mStack.end(); ++it) + { + popped.push_back(*it); + + if (it == mStackIt) fixIt = true; + + if ((*it).get() == layer) + { + ++it; + mStack.erase(mStack.begin(), it); + + for (it = popped.begin(); it != popped.end(); ++it) + { + (*it)->popped(mInterface); + } + + if (fixIt) mStackIt = --mStack.begin(); + + return popped.back(); + } + } + + return LayerP(); + } + + void clear() + { + mStack.clear(); + mStackIt = mStack.begin(); + logInfo("clear: %d", mStack.size()); + } + + + Engine& mInterface; + + VideoP mVideo; + + std::list mStack; + std::list::iterator mStackIt; + + Scalar mTimestep; + Scalar mDrawRate; + + long mFps; + bool mPrintFps; +}; + + +static Engine* instance = 0; + +Engine::Engine(int argc, char* argv[], const std::string& name, + const std::string& iconFile, const std::string& configFile) : + mImpl(new Engine::Impl(argc, argv, name, iconFile, configFile, *this)) { - return impl_->run(); + instance = this; } -void Engine::stop(int exitCode) + +Engine& Engine::getInstance() { - impl_->running = false; - impl_->exitCode = exitCode; + ASSERT(instance && "dereferencing null pointer"); + return *instance; + // TODO this has not been completely thought out + //static Engine engine; + //return engine; } +void Engine::run() +{ + return mImpl->run(); +} + void Engine::setTimestep(Scalar ts) { - impl_->timestep = ts; + mImpl->mTimestep = ts; } -Scalar Engine::getTimestep() +Scalar Engine::getTimestep() const { - return impl_->timestep; + return mImpl->mTimestep; } void Engine::setMaxFrameRate(long maxFps) { - impl_->drawRate = 1.0 / Scalar(maxFps); + mImpl->mDrawRate = 1.0 / Scalar(maxFps); } -long Engine::getMaxFrameRate() +long Engine::getMaxFrameRate() const { - return long(1.0 / impl_->drawRate); + return long(1.0 / mImpl->mDrawRate); } -Video& Engine::getVideo() +Video& Engine::getVideo() const { - return *impl_->video; + return *mImpl->mVideo; } -long Engine::getFrameRate() +long Engine::getFrameRate() const { - return impl_->fps; + return mImpl->mFps; } -void Engine::update(Scalar t, Scalar dt) {} -void Engine::draw(Scalar alpha) {} -void Engine::handleEvent(const Event& event) {} +void Engine::push(LayerP layer) +{ + // pass through + mImpl->push(layer); +} + +LayerP Engine::pop() +{ + // pass through + return mImpl->pop(); +} + +LayerP Engine::pop(Layer* layer) +{ + // pass through + return mImpl->pop(layer); +} + +void Engine::clear() +{ + // pass through + mImpl->clear(); +} } // namespace Mf