--- /dev/null
+
+/*******************************************************************************
+
+ Copyright (c) 2009, Charles McGarvey
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include <iostream>
+#include <cstdlib> // exit
+#include <string>
+#include <stdexcept>
+
+#include <SDL/SDL.h>
+#include "fastevents.h"
+
+#include "random.hh"
+#include "timer.hh"
+#include "video.hh"
+#include "settings.hh"
+#include "dispatcher.hh"
+
+#include "engine.hh"
+
+
+namespace dc {
+
+
+class engine_impl
+{
+public:
+ engine_impl(const std::string& name, int argc, char* argv[],
+ const std::string& configFile, engine* outer) : config(argc, argv),
+ interface(outer)
+ {
+ if (SDL_Init(SDL_INIT_EVERYTHING | SDL_INIT_EVENTTHREAD) != 0)
+ {
+ throw std::runtime_error(SDL_GetError());
+ }
+ if (FE_Init() != 0)
+ {
+ throw std::runtime_error(FE_GetError());
+ }
+
+ rng::seed();
+
+ config.loadFromFile(configFile);
+
+ screen = video_ptr(new video(name));
+ screen->makeActive();
+
+ timestep = 0.01;
+ config.get("engine.timestep", timestep);
+
+ long maxfps = 40;
+ config.get("engine.maxfps", maxfps);
+ drawrate = 1.0 / scalar(maxfps);
+
+ printfps = false;
+ config.get("engine.printfps", printfps);
+ }
+
+ ~engine_impl()
+ {
+ // The video object must be destroyed before we can shutdown SDL.
+ screen.reset();
+
+ FE_Quit();
+ SDL_Quit();
+ }
+
+
+ int run()
+ {
+ scalar ticksNow = ticks();
+
+ scalar nextStep = ticksNow;
+ scalar nextDraw = ticksNow;
+ scalar nextFPSUpdate = ticksNow + 1.0;
+
+ scalar totalTime = 0.0;
+ scalar accumulator = 0.0;
+
+ fps = 0.0;
+ int frameAccum = 0.0;
+
+ running = true;
+ do
+ {
+ dispatchEvents();
+
+ scalar newTicks = ticks();
+ accumulator += newTicks - ticksNow;
+ ticksNow = newTicks;
+
+ if (ticksNow >= nextStep)
+ {
+ interface->update(totalTime, timestep);
+
+ totalTime += timestep;
+ accumulator -= timestep;
+
+ nextStep += timestep;
+ if (ticksNow >= nextStep) nextStep = ticksNow + timestep;
+ }
+
+ if (ticksNow >= nextDraw)
+ {
+ frameAccum++;
+
+ if (ticksNow >= nextFPSUpdate)
+ {
+ fps = frameAccum;// + (ticksNow - nextFPSUpdate) / 1.0;
+ frameAccum = 0;
+
+ nextFPSUpdate += 1.0;
+ if (ticksNow >= nextFPSUpdate) nextFPSUpdate = ticksNow + 1.0;
+
+ if (printfps)
+ {
+ std::cout << "FPS: " << fps << std::endl;
+ }
+ }
+
+ interface->draw(accumulator / timestep);
+ screen->swap();
+
+ nextDraw += drawrate;
+ if (ticksNow >= nextDraw) nextDraw = ticksNow + drawrate;
+ }
+
+ sleep(std::min(nextStep, nextDraw), true);
+ }
+ while (running);
+ }
+
+
+ void dispatchEvents()
+ {
+ SDL_Event event;
+
+ while (FE_PollEvent(&event) == 1)
+ {
+ switch (event.type)
+ {
+ case SDL_KEYDOWN:
+ if (event.key.keysym.sym == SDLK_ESCAPE &&
+ (SDL_GetModState() & KMOD_CTRL) )
+ {
+ exit(0);
+ }
+ break;
+
+ case SDL_VIDEORESIZE:
+ screen->resize(event.resize.w, event.resize.h);
+ break;
+ }
+
+ interface->dispatchEvent(event);
+ }
+ }
+
+
+ settings config;
+ dispatcher relay;
+ video_ptr screen;
+
+ bool running;
+
+ scalar timestep;
+ scalar drawrate;
+
+ long fps;
+ bool printfps;
+
+ engine* interface;
+};
+
+engine::engine(const std::string& name, int argc, char* argv[],
+ const std::string& configFile)
+ : impl(new engine_impl(name, argc, argv, configFile, this)) {}
+
+engine::~engine() {}
+
+
+int engine::run()
+{
+ impl->run();
+}
+
+void engine::stop()
+{
+ impl->running = false;
+}
+
+
+void engine::setTimestep(scalar ts)
+{
+ impl->timestep = ts;
+}
+
+scalar engine::getTimestep()
+{
+ return impl->timestep;
+}
+
+void engine::setMaxFPS(long maxfps)
+{
+ impl->drawrate = 1.0 / scalar(maxfps);
+}
+
+long engine::getMaxFPS()
+{
+ return long(1.0 / impl->drawrate);
+}
+
+
+video& engine::getVideo()
+{
+ return *impl->screen;
+}
+
+long engine::getFPS()
+{
+ return impl->fps;
+}
+
+
+void engine::update(scalar t, scalar dt) {}
+void engine::draw(scalar alpha) {}
+void engine::dispatchEvent(const SDL_Event& event) {}
+
+
+} // namespace dc
+