X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fyoink;a=blobdiff_plain;f=src%2FMoof%2FEngine.cc;h=5d703da15d745110a4caa63d938c6fc7890bcde3;hp=16da8d40620edd59199a02e46ef43302113f8984;hb=4f62ce947db282f0bbf4d49b3aafb83d7cf51adc;hpb=a4debfe4a5f5d339410788971b698ba00cb7f09c diff --git a/src/Moof/Engine.cc b/src/Moof/Engine.cc index 16da8d4..5d703da 100644 --- a/src/Moof/Engine.cc +++ b/src/Moof/Engine.cc @@ -27,22 +27,22 @@ *******************************************************************************/ #include -#include // exit +#include // exit, srand +#include // time #include #include +#include #include #include "fastevents.h" -#include -#include "Dispatcher.hh" + #include "Engine.hh" #include "Event.hh" #include "Log.hh" -#include "Random.hh" +#include "Math.hh" #include "Settings.hh" #include "Timer.hh" -#include "Video.hh" namespace Mf { @@ -51,57 +51,84 @@ namespace Mf { class Engine::Impl { public: - Impl(int argc, char* argv[], const std::string& name, - const std::string& iconFile, const std::string& configFile, - Engine& engine) : - interface(engine), - timestep(0.01), - printFps(false) + + Impl() : + mError(Error::NONE), + mTimestep(0.01), + mFramerate(0.02), + mShowFps(false) { -#if defined(_WIN32) || defined (_WIN64) || defined(__WIN32__) +#if defined(_WIN32) || defined(__WIN32__) if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) != 0) #else if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTTHREAD) != 0) #endif { - logError("sdl is complaining: %s", SDL_GetError()); - throw Exception(Exception::SDL_ERROR); + const char* error = SDL_GetError(); + mError.init(Error::SDL_INIT, error); + return; // fatal } + else + { + char name[128]; + SDL_VideoDriverName(name, sizeof(name)); + logInfo << "initialized SDL; using video driver `" + << name << "'" << std::endl; + } + if (FE_Init() != 0) { - logError("fast events error: %s", FE_GetError()); - throw Exception(Exception::SDL_ERROR); + const char* error = FE_GetError(); + mError.init(Error::FASTEVENTS_INIT, error); + return; // fatal } - alutInit(&argc, argv); - Settings& settings = Settings::getInstance(); - settings.loadFromFile(configFile); - settings.parseArgs(argc, argv); + mAlDevice = alcOpenDevice(0); + mAlContext = alcCreateContext(mAlDevice, 0); + if (!mAlDevice || !mAlContext) + { + const char* error = alcGetString(mAlDevice,alcGetError(mAlDevice)); + mError.init(Error::OPENAL_INIT, error); + } + else + { + alcMakeContextCurrent(mAlContext); + logInfo << "opened sound device `" + << alcGetString(mAlDevice, ALC_DEFAULT_DEVICE_SPECIFIER) + << "'" << std::endl; + } + } - long randomSeed; - if (settings.get("rngseed", randomSeed)) setSeed(randomSeed); - else setSeed(); + bool initWithSettings(const Settings& settings) + { + unsigned randomSeed; + if (settings.get("rngseed", randomSeed)) srand(randomSeed); + else srand(time(0)); - Scalar timeStep = 80.0; - settings.get("timestep", timeStep); - timestep = 1.0 / timeStep; + Scalar timestep = 80.0; + settings.get("timestep", timestep); + mTimestep = 1.0 / timestep; - Scalar maxFps = 40.0; - settings.get("maxfps", maxFps); - drawRate = 1.0 / maxFps; + Scalar framerate = 40.0; + settings.get("framerate", framerate); + mFramerate = 1.0 / framerate; + capFps(); - settings.get("printfps", printFps); + mShowFps = false; + settings.get("showfps", mShowFps); - video = Video::alloc(name, iconFile); - video->makeActive(); + return true; } ~Impl() { // the video object must be destroyed before we can shutdown SDL - video.reset(); + mVideo.reset(); + + alcMakeContextCurrent(0); + alcDestroyContext(mAlContext); + alcCloseDevice(mAlDevice); - alutExit(); FE_Quit(); SDL_Quit(); } @@ -116,82 +143,59 @@ public: void run() { - Scalar ticksNow = Timer::getTicks(); + Scalar totalTime = 0.0; + Scalar ticks = Timer::getTicks(); - Scalar nextStep = ticksNow; - Scalar nextDraw = ticksNow; - Scalar nextFpsUpdate = ticksNow + 1.0; + Scalar nextUpdate = ticks; + Scalar nextDraw = ticks; + Scalar nextSecond = ticks + SCALAR(1.0); - Scalar totalTime = 0.0; - Scalar deltaTime = 0.0; - Scalar accumulator = timestep; + mFps = 0; + int frames = 0; - fps = 0; - int frameAccum = 0; + const int MAX_FRAMESKIP = 15; + const Scalar inverseTimestep = SCALAR(1.0) / mTimestep; do { - Scalar newTicks = Timer::getTicks(); - deltaTime = newTicks - ticksNow; - ticksNow = newTicks; - - if (deltaTime >= 0.25) deltaTime = 0.25; - accumulator += deltaTime; + Timer::fireIfExpired(); + dispatchEvents(); - Timer::fireIfExpired(ticksNow); - - while (accumulator >= timestep) + int i = 0; + while (nextUpdate < Timer::getTicks() && i < MAX_FRAMESKIP) { - dispatchEvents(); - update(totalTime, timestep); - - totalTime += timestep; - accumulator -= timestep; + totalTime += mTimestep; + update(totalTime, mTimestep); - nextStep += timestep; - } - if (ticksNow >= nextStep) - { - nextStep = ticksNow + timestep; + nextUpdate += mTimestep; + ++i; } - if (ticksNow >= nextDraw) + if (nextDraw < (ticks = Timer::getTicks())) { - frameAccum++; - - if (ticksNow >= nextFpsUpdate) // determine the actual fps - { - fps = frameAccum; - frameAccum = 0; + ++frames; + draw((ticks + mTimestep - nextUpdate) * inverseTimestep); + mVideo->swap(); - nextFpsUpdate += 1.0; - if (ticksNow >= nextFpsUpdate) - { - nextFpsUpdate = ticksNow + 1.0; - } + nextDraw += mFramerate; - if (printFps) - { - logInfo("%d fps", fps); - } - } + if (mShowFps && nextSecond < ticks) + { + mFps = frames; + frames = 0; - draw(accumulator / timestep); - video->swap(); + logInfo << mFps << " fps" << std::endl; - nextDraw += drawRate; - if (ticksNow >= nextDraw) - { - // we missed some scheduled draws, so reset the schedule - nextDraw = ticksNow + drawRate; + nextSecond += SCALAR(1.0); } } // be a good citizen and give back what you don't need - Timer::sleep(std::min(std::min(nextStep, nextDraw), - Timer::getNextFire()), true); + Timer::sleep(0.0); } - while (!stack.empty()); + while (!mStack.empty()); + + mDispatch.dispatch("engine.stopping"); } void dispatchEvents() @@ -207,12 +211,13 @@ public: (SDL_GetModState() & KMOD_CTRL) ) { // emergency escape - exit(0); + logWarning("escape forced"); + exit(1); } break; case SDL_VIDEORESIZE: - video->resize(event.resize.w, event.resize.h); + mVideo->resize(event.resize.w, event.resize.h); break; } @@ -223,9 +228,9 @@ public: void update(Scalar t, Scalar dt) { - for (stackIt = stack.begin(); stackIt != stack.end(); ++stackIt) + for (mStackIt = mStack.begin(); mStackIt != mStack.end(); ++mStackIt) { - (*stackIt)->update(t, dt); + (*mStackIt)->update(t, dt); } } @@ -233,7 +238,7 @@ public: { // FIXME - this will crash if the layer being drawn pops itself std::list::reverse_iterator it; - for (it = stack.rbegin(); it != stack.rend(); ++it) + for (it = mStack.rbegin(); it != mStack.rend(); ++it) { (*it)->draw(alpha); } @@ -241,9 +246,9 @@ public: void handleEvent(const Event& event) { - for (stackIt = stack.begin(); stackIt != stack.end(); ++stackIt) + for (mStackIt = mStack.begin(); mStackIt != mStack.end(); ++mStackIt) { - if ((*stackIt)->handleEvent(event)) break; + if ((*mStackIt)->handleEvent(event)) break; } } @@ -251,52 +256,56 @@ public: void push(LayerP layer) { ASSERT(layer && "cannot push null layer"); - stack.push_front(layer); - logInfo(" push: %d", stack.size()); - layer->pushed(interface); + mStack.push_front(layer); + logInfo << "stack: " << mStack.size() + << " [pushed " << layer.get() << "]" << std::endl; + layer->pushedOntoEngine(); } LayerP pop() { bool fixIt = false; - if (stack.begin() == stackIt) fixIt = true; + if (mStack.begin() == mStackIt) fixIt = true; - LayerP popped = stack.front(); - stack.pop_front(); - logInfo(" pop: %d", stack.size()); - popped->popped(interface); + LayerP layer = mStack.front(); + mStack.pop_front(); + logInfo << "stack: " << mStack.size() + << " [popped " << layer.get() << "]" << std::endl; + layer->poppedFromEngine(); - if (fixIt) stackIt = --stack.begin(); + if (fixIt) mStackIt = --mStack.begin(); - return popped; + return layer; } LayerP pop(Layer* layer) { bool fixIt = false; - std::list popped; + std::list layers; std::list::iterator it; - for (it = stack.begin(); it != stack.end(); ++it) + for (it = mStack.begin(); it != mStack.end(); ++it) { - popped.push_back(*it); + layers.push_back(*it); - if (it == stackIt) fixIt = true; + if (it == mStackIt) fixIt = true; if ((*it).get() == layer) { ++it; - stack.erase(stack.begin(), it); + mStack.erase(mStack.begin(), it); - for (it = popped.begin(); it != popped.end(); ++it) + for (it = layers.begin(); it != layers.end(); ++it) { - (*it)->popped(interface); + (*it)->poppedFromEngine(); + logInfo << "stack: " << mStack.size() + << " [popped " << (*it).get() << "]" << std::endl; } - if (fixIt) stackIt = --stack.begin(); + if (fixIt) mStackIt = --mStack.begin(); - return popped.back(); + return layers.back(); } } @@ -305,108 +314,143 @@ public: void clear() { - stack.clear(); - stackIt = stack.begin(); - logInfo("clear: %d", stack.size()); + mStack.clear(); + mStackIt = mStack.begin(); + logInfo("stack: 0 [cleared]"); + } + + + void capFps() + { + //if (mFramerate < mTimestep) + //{ + //logWarning << "capping maximum fps to timestep (" + //<< mTimestep << ")" << std::endl; + //mFramerate = mTimestep; + //} } - Engine& interface; + Error mError; - VideoP video; + VideoP mVideo; + Dispatch mDispatch; - std::list stack; - std::list::iterator stackIt; + ALCdevice* mAlDevice; + ALCcontext* mAlContext; - Scalar timestep; - Scalar drawRate; + std::list mStack; + std::list::iterator mStackIt; - long fps; - bool printFps; + Scalar mTimestep; + Scalar mFramerate; + + int mFps; + bool mShowFps; }; -static Engine* instance = 0; +Engine::Engine() : + // pass through + mImpl(new Engine::Impl) {} + -Engine::Engine(int argc, char* argv[], const std::string& name, - const std::string& iconFile, const std::string& configFile) : - impl_(new Engine::Impl(argc, argv, name, iconFile, configFile, *this)) +bool Engine::initWithSettings(const Settings& settings) { - instance = this; + // pass through + return mImpl->initWithSettings(settings); } +const Error& Engine::getError() const +{ + // pass through + return mImpl->mError; +} -Engine& Engine::getInstance() +void Engine::clearError() { - ASSERT(instance && "dereferencing null pointer"); - return *instance; - //static Engine engine; - //return engine; + // pass through + mImpl->mError.init(Error::NONE); } -void Engine::run() +void Engine::setVideo(VideoP video) { - return impl_->run(); + // pass through + mImpl->mVideo = video; } -void Engine::setTimestep(Scalar ts) +VideoP Engine::getVideo() const { - impl_->timestep = ts; + return mImpl->mVideo; } -Scalar Engine::getTimestep() const + +int Engine::getFps() const { - return impl_->timestep; + return mImpl->mFps; } -void Engine::setMaxFrameRate(long maxFps) + +void Engine::push(LayerP layer) { - impl_->drawRate = 1.0 / Scalar(maxFps); + // pass through + mImpl->push(layer); } -long Engine::getMaxFrameRate() const +LayerP Engine::pop() { - return long(1.0 / impl_->drawRate); + // pass through + return mImpl->pop(); } +LayerP Engine::pop(Layer* layer) +{ + // pass through + return mImpl->pop(layer); +} -Video& Engine::getVideo() const +void Engine::clear() { - return *impl_->video; + // pass through + mImpl->clear(); } -long Engine::getFrameRate() const +int Engine::getSize() const { - return impl_->fps; + return mImpl->mStack.size(); } -void Engine::push(LayerP layer) +void Engine::run() { // pass through - impl_->push(layer); + return mImpl->run(); } -LayerP Engine::pop() + +Dispatch::Handler Engine::addHandler(const std::string& event, + const Dispatch::Function& callback) { - // pass through - return impl_->pop(); + return mImpl->mDispatch.addHandler(event, callback); } -LayerP Engine::pop(Layer* layer) +Dispatch::Handler Engine::addHandler(const std::string& event, + const Dispatch::Function& callback, Dispatch::Handler handler) { - // pass through - return impl_->pop(layer); + return mImpl->mDispatch.addHandler(event, callback, handler); } -void Engine::clear() +void Engine::dispatch(const std::string& event, + const Dispatch::Message* message) { - // pass through - impl_->clear(); + mImpl->mDispatch.dispatch(event, message); } +Engine engine; + + } // namespace Mf /** vim: set ts=4 sw=4 tw=80: *************************************************/