will be used. The default value is true.
.TP
.B framerate
-The maximum number of frames to be drawn per second. If your computer is
+The target number of frames to be drawn per second. If your computer is
really old, you can get away with decreasing this value and still have
reasonably smooth animation. You can set this to a very high number to
effectively render as many frames as is possible, but the actual rate could
be limited by vertical display synchronization, depending on the X11 driver
-and settings used. You should not set this option higher than the point
-where the vertical synchronization effectively limits the draw rate or else
-the game may not be able to update the physics on schedule which could
-actually significantly lower the quality of the animation. The default
-value is 40.
+and settings used. The default value is 50.
.TP
.B fullscreen
If true, the window will capture the display and render the game in full
.SH EXAMPLES
Here are some examples of typical usage:
.TP
-$ yoink framerate=60
-Cap the allowable frame-rate to 60Hz.
+$ yoink detail=2
+Set the level of detail to 2 so that less stuff is drawn to the screen.
.TP
-$ yoink fullscreen=true
-Run \fByoink\fP in full-screen mode.
-.TP
-$ yoink videomode=\\{1024,768\\}
-Run \fByoink\fP with a resolution of 1024x768. Notice the escapes for the
-curly braces so the shell doesn't parse them.
+$ yoink fullscreen=true videomode=\\{1024,768\\}
+Run \fByoink\fP at full screen with a resolution of 1024x768. Notice the
+escapes for the curly braces so the shell doesn't parse them.
.SH ENVIRONMENT
\fByoink\fP responds to some variables in the environment:
.TP
.I HOME
-If set to a path of a valid directory (presumably a user's home directory),
+If set to a path of a valid directory (presumably your home directory),
\fByoink\fP will look for a file at \fI$HOME/.yoinkrc\fP and load it as a
config file.
.TP
.TP
2. Decrease the level of rendering detail.
Use the \fBdetail\fP option. The game world may look sparse or incomplete,
-but that's probably better than choppy animation.
-.TP
-3. Decrease the timestep.
-You can set the \fBtimestep\fP to be as low as the your \fBframerate\fP
-option. Remember the trade-off here is decreased simulation accuracy.
+but that's probably better than choppy animation if you can avoid it.
+.TP
+3. Decrease the framerate and/or timestep.
+If your machine can't meet the target framerate, your actual framerate will
+probably vary. You will have a better visual experience if you can reduce
+the \fBframerate\fP to a point such that the actual framerate is basically
+constant. A constant 20fps or 30fps will look better than a sporadic
+40-60fps. You can also decrease the \fBtimestep\fP at the expense of
+decreased simulation accuracy. You'll have to experiment with this value
+to find out acceptable levels.
.PP
If you are having audio problems, you may need to upgrade OpenAL. Some
systems still provide an old, busted version of OpenAL which may result in
*******************************************************************************/
-#include <Moof/Engine.hh>
+#include <Moof/Core.hh>
#include <Moof/Error.hh>
#include <Moof/Log.hh>
#include <Moof/Math.hh>
mMusic.enqueue("NightFusionLoop");
bool isMute = false;
- Mf::Settings::getInstance().get("nomusic", isMute);
+ Mf::settings.get("nomusic", isMute);
if (!isMute) mMusic.play();
//mMusic.setPosition(Mf::Vector3(10.0, 5.0, 0.0));
void GameLayer::pushedOntoEngine()
{
- Mf::engine.push(mHud);
+ Mf::core.push(mHud);
mRay.direction.set(1.0, 0.0);
case SDL_KEYUP:
if (event.key.keysym.sym == SDLK_ESCAPE)
{
- Mf::engine.pop(this);
+ Mf::core.pop(this);
return true;
}
else if (event.key.keysym.sym == SDLK_h)
{
- Mf::engine.push(mHud);
+ Mf::core.push(mHud);
return true;
}
return mState.heroine->handleEvent(event);
void GameLayer::setProjection()
{
- Mf::VideoP video = Mf::engine.getVideo();
- setProjection(video->getWidth(), video->getHeight());
+ ASSERT(Mf::video && "no current video context from which to get dimensions");
+ setProjection(Mf::video->getWidth(), Mf::video->getHeight());
}
void GameLayer::setProjection(Mf::Scalar width, Mf::Scalar height)
*******************************************************************************/
-#include <Moof/Engine.hh>
+#include <Moof/Core.hh>
#include <Moof/OpenGL.hh>
#include <Moof/Video.hh>
mBar2(Tilemap("StatusBars"), 2),
mFont("Font")
{
- Mf::VideoP video = Mf::engine.getVideo();
- resize(video->getWidth(), video->getHeight());
+ ASSERT(Mf::video && "no current video context from which to get dimensions");
+ resize(Mf::video->getWidth(), Mf::video->getHeight());
}
}
-void Hud::update(Mf::Engine& engine, Mf::Scalar t, Mf::Scalar dt)
+void Hud::update(Mf::Scalar t, Mf::Scalar dt)
{
mState.interp.update(t, dt);
setBar1Progress(mState.interp.getState(dt));
setBar2Progress(1.0 - mState.interp.getState(dt));
}
-void Hud::draw(Mf::Engine& engine, Mf::Scalar alpha) const
+void Hud::draw(Mf::Scalar alpha) const
{
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glPopMatrix();
}
-bool Hud::handleEvent(Mf::Engine& engine, const Mf::Event& event)
+bool Hud::handleEvent(const Mf::Event& event)
{
switch (event.type)
{
if (event.key.keysym.sym == SDLK_h)
{
// don't want the hud anymore
- engine.pop(this);
+ Mf::core.pop(this);
return true;
}
break;
void resize(int width, int height);
- void update(Mf::Engine& engine, Mf::Scalar t, Mf::Scalar dt);
- void draw(Mf::Engine& engine, Mf::Scalar alpha = 0.0) const;
- bool handleEvent(Mf::Engine& engine, const Mf::Event& event);
+ void update(Mf::Scalar t, Mf::Scalar dt);
+ void draw(Mf::Scalar alpha = 0.0) const;
+ bool handleEvent(const Mf::Event& event);
private:
#include "ErrorHandler.hh"
#include "GameLayer.hh"
-#include "MainLayer.hh"
+#include "Main.hh"
#include "TitleLayer.hh"
#if HAVE_CONFIG_H
#include "version.h"
-MainLayer::MainLayer()
+Main::Main()
{
- mDispatchHandler = Mf::engine.addHandler("video.newcontext",
- boost::bind(&MainLayer::contextRecreated, this));
+ mDispatchHandler = Mf::core.addHandler("video.newcontext",
+ boost::bind(&Main::contextRecreated));
setupGL();
}
-void MainLayer::pushedOntoEngine()
+void Main::addedToCore()
{
//Mf::Scalar coeff[] = {0.0, 1.0};
//Mf::Lerp interp(coeff, 0.25);
//Mf::LayerP gameLayer = GameLayer::alloc();
//Mf::Transition<Mf::Lerp>::Ptr transition =
//Mf::Transition<Mf::Lerp>::alloc(gameLayer, Mf::LayerP(), interp);
- //engine->push(transition);
- //engine->push(GameLayer::alloc());
- Mf::engine.push(TitleLayer::alloc());
+ //core.push(transition);
+ //core.push(GameLayer::alloc());
+ Mf::core.push(TitleLayer::alloc());
}
-void MainLayer::update(Mf::Scalar t, Mf::Scalar dt)
+void Main::update(Mf::Scalar t, Mf::Scalar dt)
{
- if (Mf::engine.getSize() == 1)
+ if (Mf::core.getSize() == 1)
{
// this is the only layer left on the stack
- //Mf::engine.push(TitleLayer::alloc());
- Mf::engine.clear();
+ //Mf::core.push(TitleLayer::alloc());
+ Mf::core.clear();
}
}
-void MainLayer::draw(Mf::Scalar alpha) const
+void Main::draw(Mf::Scalar alpha) const
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
}
-bool MainLayer::handleEvent(const Mf::Event& event)
+bool Main::handleEvent(const Mf::Event& event)
{
switch (event.type)
{
case SDL_KEYUP:
if (event.key.keysym.sym == SDLK_ESCAPE)
{
- Mf::engine.clear();
+ Mf::core.clear();
}
else if (event.key.keysym.sym == SDLK_f)
{
- Mf::engine.getVideo()->toggleFull();
+ Mf::video->toggleFull();
}
else if (event.key.keysym.sym == SDLK_l)
{
- Mf::VideoP video = Mf::engine.getVideo();
- video->toggleCursorGrab();
- video->toggleCursorVisible();
+ Mf::video->toggleCursorGrab();
+ Mf::video->toggleCursorVisible();
}
break;
break;
case SDL_QUIT:
- Mf::engine.clear();
+ Mf::core.clear();
break;
}
}
-void MainLayer::setupGL()
+std::string Main::getSearchPath()
+{
+ // Add search paths; they should be searched in this order:
+ // 1. YOINK_DATADIR (environment)
+ // 2. YOINK_DATADIR (configure)
+
+ std::string path;
+
+ char* dataDir = getenv("YOINK_DATADIR");
+ if (dataDir)
+ {
+ path += dataDir;
+ path += ":";
+ }
+ path += YOINK_DATADIR;
+
+ return path;
+}
+
+std::string Main::getConfigPath()
+{
+ // Build the list of config files to search for, in this order:
+ // 1. YOINK_DATADIR/yoinkrc
+ // 2. /etc/yoinkrc (not for Windows)
+ // 3. $HOME/.yoinkrc
+ // 4. YOINKRC (environment)
+
+ std::string path = Mf::Resource::getPath("yoinkrc");
+
+#if !defined(_WIN32) && !defined(__WIN32__)
+ path += ":/etc/yoinkrc";
+#endif
+ path += ":$HOME/.yoinkrc";
+
+ char* configFile = getenv("YOINKRC");
+ if (configFile)
+ {
+ path += ":";
+ path += configFile;
+ }
+
+ return path;
+}
+
+
+void Main::setupGL()
{
glEnable(GL_TEXTURE_2D);
glEnable(GL_DEPTH_TEST);
//glMatrixMode(GL_PROJECTION);
//glLoadIdentity();
- //Mf::Scalar ratio = Mf::engine.getVideo()->getWidth() /
- //Mf::engine.getVideo()->getHeight();
+ //Mf::Scalar ratio = Mf::core.getVideo()->getWidth() /
+ //Mf::core.getVideo()->getHeight();
//gluPerspective(60.0, ratio, 1.0, 250.0);
//glMatrixMode(GL_MODELVIEW);
}
-void MainLayer::contextRecreated()
+void Main::contextRecreated()
{
// whenever the context is destroyed and a new one created, it probably
// won't contain our state so we need to set that up again
-void printUsage()
+void Main::printUsage()
{
std::cout << "Usage: "PACKAGE" [-h|--help] [-i|--info] [OPTION=VALUE]..."
<< std::endl
<< " the level of detail of game scenes" << std::endl
<< " fullscreen=true|false" << std::endl
<< " if true, uses the entire display" << std::endl
- << " maxfps=num" << std::endl
- << " the maximum number of frames per second" << std::endl
+ << " framerate=num" << std::endl
+ << " the target number of frames per second" << std::endl
<< std::endl
<< "See documentation for more options." << std::endl;
}
-void printInfo(int argc, char* argv[])
+void Main::printInfo(int argc, char* argv[])
{
std::string assets;
std::string datadir;
<< "YOINK_DATADIR: " << datadir << std::endl;
}
+
+void hello()
+{
+ std::cout << std::endl << PACKAGE_STRING << std::endl
+ << "Compiled " << __TIME__ " " __DATE__ << std::endl
+ << "Send patches and bug reports to <"
+ PACKAGE_BUGREPORT << ">." << std::endl << std::endl;
+}
+
void goodbye()
{
std::cout << std::endl << "Goodbye..." << std::endl << std::endl;
}
-
int main(int argc, char* argv[])
{
if (argc > 1)
std::string arg(argv[1]);
if (arg == "-h" || arg == "--help")
{
- printUsage();
+ Main::printUsage();
return 0;
}
else if (arg == "-i" || arg == "--info")
{
- printInfo(argc, argv);
+ Main::printInfo(argc, argv);
return 0;
}
}
-
- std::cout << std::endl << PACKAGE_STRING << std::endl
- << "Compiled " << __TIME__ " " __DATE__ << std::endl
- << "Send patches and bug reports to <"
- PACKAGE_BUGREPORT << ">." << std::endl << std::endl;
-
+ hello();
atexit(goodbye);
+ Mf::Resource::addSearchPaths(Main::getSearchPath());
- // make sure the engine started up okay
- const Mf::Error& error = Mf::engine.getError();
- if (error.isError())
- {
- Mf::ModalDialog dialog;
- dialog.title = PACKAGE_STRING;
- dialog.text1 = "Uh oh!";
- dialog.text2 = getErrorString(error);
- dialog.type = Mf::ModalDialog::CRITICAL;
- dialog.run();
-
- // openal errors are not fatal
- if (error.code() != Mf::Error::OPENAL_INIT) return 1;
- }
-
-
- // Add search paths; they should be searched in this order:
- // 1. YOINK_DATADIR (environment)
- // 2. YOINK_DATADIR (configure)
-
- char* dataDir = getenv("YOINK_DATADIR");
- if (dataDir)
- {
- Mf::Resource::addSearchPath(dataDir);
- }
-
- Mf::Resource::addSearchPath(YOINK_DATADIR);
-
-
- // Build the list of config files to search for, in this order:
- // 1. YOINK_DATADIR/yoinkrc
- // 2. /etc/yoinkrc (not for Windows)
- // 3. $HOME/.yoinkrc
- // 4. YOINKRC (environment)
-
- std::string configFiles = Mf::Resource::getPath("yoinkrc");
-#if !defined(_WIN32) && !defined(__WIN32__)
- configFiles += ":/etc/yoinkrc";
-#endif
- configFiles += ":$HOME/.yoinkrc";
-
- char* configFile = getenv("YOINKRC");
- if (configFile)
- {
- configFiles += ":";
- configFiles += configFile;
- }
-
- Mf::Settings& settings = Mf::Settings::getInstance();
- settings.loadFromFile(configFiles);
- settings.parseArgs(argc, argv);
+ Mf::settings.loadFromFiles(Main::getConfigPath());
+ Mf::settings.parseArgs(argc, argv);
Mf::Log::Level logLevel;
- if (settings.get("loglevel", logLevel)) Mf::Log::setLevel(logLevel);
-
- Mf::engine.initWithSettings(settings);
-
- std::string iconFile = Mf::Resource::getPath(PACKAGE".png");
-
+ if (Mf::settings.get("loglevel", logLevel)) Mf::Log::setLevel(logLevel);
try
{
- Mf::engine.setVideo(Mf::Video::alloc(PACKAGE_STRING, iconFile));
- Mf::engine.push(MainLayer::alloc());
-
- Mf::engine.run();
+ Mf::Video video(PACKAGE_STRING, Mf::Resource::getPath(PACKAGE".png"));
+ MainP app = Main::alloc();
+ Mf::core.push(app);
+ Mf::core.run();
}
catch (const Mf::Error& error)
{
*******************************************************************************/
-#ifndef _MAINLAYER_HH_
-#define _MAINLAYER_HH_
+#ifndef _YOINKAPP_HH_
+#define _YOINKAPP_HH_
/**
- * @file MainLayer.hh
+ * @file Main.hh
* This is where all the fun begins.
*/
#include <boost/shared_ptr.hpp>
#include <Moof/Dispatch.hh>
-#include <Moof/Engine.hh>
#include <Moof/Layer.hh>
#include <Moof/Math.hh>
-class MainLayer;
-typedef boost::shared_ptr<MainLayer> MainLayerP;
+class Main;
+typedef boost::shared_ptr<Main> MainP;
-class MainLayer : public Mf::Layer
+class Main : public Mf::Layer
{
public:
- MainLayer();
+ Main();
- static MainLayerP alloc()
+ static MainP alloc()
{
- return MainLayerP(new MainLayer);
+ return MainP(new Main);
}
- void pushedOntoEngine();
+ void addedToCore();
void update(Mf::Scalar t, Mf::Scalar dt);
void draw(Mf::Scalar alpha) const;
bool handleEvent(const Mf::Event& event);
+ static std::string getSearchPath();
+ static std::string getConfigPath();
+
+ static void printUsage();
+ static void printInfo(int argc, char* argv[]);
+
private:
/**
* Set OpenGL to a state we can know and depend on.
*/
- void setupGL();
- void contextRecreated();
+ static void setupGL();
+ static void contextRecreated();
Mf::Dispatch::Handler mDispatchHandler;
};
-#endif // _MAINLAYER_HH_
+#endif // _YOINKAPP_HH_
/** vim: set ts=4 sw=4 tw=80: *************************************************/
Moof/Camera.hh \
Moof/ConvertUTF.c \
Moof/ConvertUTF.h \
+ Moof/Core.cc \
+ Moof/Core.hh \
Moof/Cullable.hh \
Moof/Dispatch.cc \
Moof/Dispatch.hh \
Moof/Drawable.hh \
- Moof/Engine.cc \
- Moof/Engine.hh \
Moof/Entity.hh \
Moof/Event.hh \
Moof/Exception.hh \
Heroine.hh \
Hud.cc \
Hud.hh \
- MainLayer.cc \
- MainLayer.hh \
+ Main.cc \
+ Main.hh \
Scene.cc \
Scene.hh \
Tilemap.cc \
#include <SDL/SDL.h>
#include "fastevents.h"
-
-#include "Engine.hh"
+#include "Core.hh"
#include "Event.hh"
#include "Log.hh"
#include "Math.hh"
+#include "ModalDialog.hh"
#include "Settings.hh"
#include "Timer.hh"
+#include "Video.hh"
namespace Mf {
-class Engine::Impl
+class Core::Impl
{
public:
mError(Error::NONE),
mTimestep(0.01),
mFramerate(0.02),
- mShowFps(false)
- {
-#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
- {
- 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)
- {
- const char* error = FE_GetError();
- mError.init(Error::FASTEVENTS_INIT, error);
- return; // fatal
- }
-
- 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;
- }
- }
+ mShowFps(false) {}
- bool initWithSettings(const Settings& settings)
+ void init()
{
unsigned randomSeed;
if (settings.get("rngseed", randomSeed)) srand(randomSeed);
Scalar framerate = 40.0;
settings.get("framerate", framerate);
mFramerate = 1.0 / framerate;
- capFps();
mShowFps = false;
settings.get("showfps", mShowFps);
-
- return true;
- }
-
- ~Impl()
- {
- // the video object must be destroyed before we can shutdown SDL
- mVideo.reset();
-
- alcMakeContextCurrent(0);
- alcDestroyContext(mAlContext);
- alcCloseDevice(mAlDevice);
-
- FE_Quit();
- SDL_Quit();
}
void run()
{
+ init();
+
Scalar totalTime = 0.0;
Scalar ticks = Timer::getTicks();
const int MAX_FRAMESKIP = 15;
const Scalar inverseTimestep = SCALAR(1.0) / mTimestep;
+ ASSERT(video && "cannot run core without a current video context");
+
do
{
Timer::fireIfExpired();
{
++frames;
draw((ticks + mTimestep - nextUpdate) * inverseTimestep);
- mVideo->swap();
+ video->swap();
nextDraw += mFramerate;
mDispatch.dispatch("engine.stopping");
}
+
void dispatchEvents()
{
SDL_Event event;
break;
case SDL_VIDEORESIZE:
- mVideo->resize(event.resize.w, event.resize.h);
+ video->resize(event.resize.w, event.resize.h);
break;
}
mStack.push_front(layer);
logInfo << "stack: " << mStack.size()
<< " [pushed " << layer.get() << "]" << std::endl;
- layer->pushedOntoEngine();
+ layer->addedToCore();
}
LayerP pop()
mStack.pop_front();
logInfo << "stack: " << mStack.size()
<< " [popped " << layer.get() << "]" << std::endl;
- layer->poppedFromEngine();
+ layer->removedFromCore();
if (fixIt) mStackIt = --mStack.begin();
for (it = layers.begin(); it != layers.end(); ++it)
{
- (*it)->poppedFromEngine();
+ (*it)->removedFromCore();
logInfo << "stack: " << mStack.size()
<< " [popped " << (*it).get() << "]" << std::endl;
}
}
- void capFps()
- {
- //if (mFramerate < mTimestep)
- //{
- //logWarning << "capping maximum fps to timestep ("
- //<< mTimestep << ")" << std::endl;
- //mFramerate = mTimestep;
- //}
- }
-
-
Error mError;
- VideoP mVideo;
Dispatch mDispatch;
- ALCdevice* mAlDevice;
- ALCcontext* mAlContext;
-
std::list<LayerP> mStack;
std::list<LayerP>::iterator mStackIt;
};
-Engine::Engine() :
+Core::Core() :
// pass through
- mImpl(new Engine::Impl) {}
+ mImpl(new Core::Impl) {}
-bool Engine::initWithSettings(const Settings& settings)
+void Core::init()
{
// pass through
- return mImpl->initWithSettings(settings);
-}
-
-const Error& Engine::getError() const
-{
- // pass through
- return mImpl->mError;
-}
-
-void Engine::clearError()
-{
- // pass through
- mImpl->mError.init(Error::NONE);
+ mImpl->init();
}
-void Engine::setVideo(VideoP video)
-{
- // pass through
- mImpl->mVideo = video;
-}
-
-VideoP Engine::getVideo() const
-{
- return mImpl->mVideo;
-}
-
-
-int Engine::getFps() const
+int Core::getFps() const
{
return mImpl->mFps;
}
-void Engine::push(LayerP layer)
+void Core::push(LayerP layer)
{
// pass through
mImpl->push(layer);
}
-LayerP Engine::pop()
+LayerP Core::pop()
{
// pass through
return mImpl->pop();
}
-LayerP Engine::pop(Layer* layer)
+LayerP Core::pop(Layer* layer)
{
// pass through
return mImpl->pop(layer);
}
-void Engine::clear()
+void Core::clear()
{
// pass through
mImpl->clear();
}
-int Engine::getSize() const
+int Core::getSize() const
{
return mImpl->mStack.size();
}
-void Engine::run()
+void Core::run()
{
// pass through
return mImpl->run();
}
-Dispatch::Handler Engine::addHandler(const std::string& event,
+Dispatch::Handler Core::addHandler(const std::string& event,
const Dispatch::Function& callback)
{
return mImpl->mDispatch.addHandler(event, callback);
}
-Dispatch::Handler Engine::addHandler(const std::string& event,
+Dispatch::Handler Core::addHandler(const std::string& event,
const Dispatch::Function& callback, Dispatch::Handler handler)
{
return mImpl->mDispatch.addHandler(event, callback, handler);
}
-void Engine::dispatch(const std::string& event,
+void Core::dispatch(const std::string& event,
const Dispatch::Message* message)
{
mImpl->mDispatch.dispatch(event, message);
}
-Engine engine;
+Core core;
+
+
+class Backend_;
+typedef boost::shared_ptr<Backend_> BackendP;
+
+class Backend_
+{
+public:
+
+ void init()
+ {
+#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
+ {
+ const char* error = SDL_GetError();
+ gError.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)
+ {
+ const char* error = FE_GetError();
+ gError.init(Error::FASTEVENTS_INIT, error);
+ return; // fatal
+ }
+
+ mAlDevice = alcOpenDevice(0);
+ mAlContext = alcCreateContext(mAlDevice, 0);
+ if (!mAlDevice || !mAlContext)
+ {
+ const char* error = alcGetString(mAlDevice,alcGetError(mAlDevice));
+ gError.init(Error::OPENAL_INIT, error);
+ return;
+ }
+ else
+ {
+ alcMakeContextCurrent(mAlContext);
+ logInfo << "opened sound device `"
+ << alcGetString(mAlDevice, ALC_DEFAULT_DEVICE_SPECIFIER)
+ << "'" << std::endl;
+ }
+
+ gError.init(Error::NONE);
+ }
+
+ ~Backend_()
+ {
+ alcMakeContextCurrent(0);
+ alcDestroyContext(mAlContext);
+ alcCloseDevice(mAlDevice);
+
+ FE_Quit();
+ SDL_Quit();
+ }
+
+ static void retain()
+ {
+ if (gRetainCount++ == 0)
+ {
+ gInstance = BackendP(new Backend_);
+ gInstance->init();
+ }
+ }
+
+ static void release()
+ {
+ if (--gRetainCount == 0)
+ {
+ gInstance.reset();
+ gError.reset();
+ }
+ }
+
+ static bool check(Error& error)
+ {
+ error = gError;
+ return error.code() == Error::NONE;
+ }
+
+private:
+
+ ALCdevice* mAlDevice;
+ ALCcontext* mAlContext;
+
+ static Error gError;
+ static int gRetainCount;
+ static BackendP gInstance;
+};
+
+Error Backend_::gError(Error::UNINITIALIZED);
+int Backend_::gRetainCount = 0;
+BackendP Backend_::gInstance;
+
+
+Backend::Backend()
+{
+ Backend_::retain();
+}
+
+Backend::~Backend()
+{
+ Backend_::release();
+}
+
+bool Backend::check(Error& error)
+{
+ return Backend_::check(error);
+}
} // namespace Mf
*******************************************************************************/
-#ifndef _MOOF_ENGINE_HH_
-#define _MOOF_ENGINE_HH_
+#ifndef _MOOF_CORE_HH_
+#define _MOOF_CORE_HH_
#include <boost/shared_ptr.hpp>
#include <Moof/Dispatch.hh>
#include <Moof/Error.hh>
-#include <Moof/Video.hh>
#include <Moof/Layer.hh>
namespace Mf {
-class Settings;
-
-
/**
- * The engine is essentially a stack of layers. While running, it updates each
+ * The core is essentially a stack of layers. While running, it updates each
* layer from the bottom up every timestep. It also draws each layer from the
* bottom up, adhering to the maximum frame-rate. Events are sent to each layer
- * from the top down until a layer signals the event was handled. The engine is
- * also responsible for firing timers on time. The engine will continue running
+ * from the top down until a layer signals the event was handled. The core is
+ * also responsible for firing timers on time. The core will continue running
* as long as there are layers on the stack.
*/
-class Engine
+class Core
{
public:
- Engine();
- ~Engine() {}
+ Core();
// loads settings: rngseed, timestep, framerate, showfps
- bool initWithSettings(const Settings& settings);
-
- const Error& getError() const;
- void clearError();
-
- // setting the video is required before you can run the engine and should
- // probably be done before adding any layers
- void setVideo(VideoP video);
- VideoP getVideo() const;
+ void init();
int getFps() const;
void push(LayerP layer); // push a layer onto the top
LayerP pop(); // pop the top layer
LayerP pop(Layer* layer); // pops a specific layer and all layers above it
- void clear(); // remove all layers (the engine will stop)
+ void clear(); // remove all layers (the core will stop)
int getSize() const; // get the size of the stack
boost::shared_ptr<Impl> mImpl;
};
+extern Core core;
+
+
+/*
+ * Some classes and subsystems require certain backend libraries to be
+ * initialized. This is the mechanism to accomplish that. Classes which rely
+ * on any backend libraries just need to instantiate this class as a member.
+ * Backend cleanup will occur automagically when there are no more instances.
+ */
+
+class Backend
+{
+public:
+
+ Backend();
+ ~Backend();
-extern Engine engine;
+ static bool check(Error& error);
+};
} // namespace Mf
-#endif // _MOOF_ENGINE_HH_
+#endif // _MOOF_CORE_HH_
/** vim: set ts=4 sw=4 tw=80: *************************************************/
return mCode != NONE;
}
+ void reset() throw()
+ {
+ mCode = NONE;
+ mWhat[0] = '\0';
+ }
+
private:
unsigned mCode;
#include <SDL/SDL.h>
#include <png.h>
+#include "Core.hh"
+#include "Error.hh"
#include "Image.hh"
#include "Library.hh"
#include "Log.hh"
private:
+ Backend mBackend;
+
bool init(const std::string& filePath, bool flipped)
{
logInfo("opening image file...");
virtual ~Layer() {}
- virtual void pushedOntoEngine() {}
- virtual void poppedFromEngine() {}
+ virtual void addedToCore() {}
+ virtual void removedFromCore() {}
virtual void update(Scalar t, Scalar dt) {}
virtual void draw(Scalar alpha) const {}
}
-static std::ofstream nullLog_;
-
std::ostream& log(std::clog);
+
+static std::ofstream nullLog_;
std::ostream& nullLog(nullLog_);
Log logError(Log::ERRORR, " error: ");
// static member
-std::vector<std::string> Resource::searchPaths_;
+std::vector<std::string> Resource::gSearchPaths;
-void Resource::addSearchPath(const std::string& directory)
+void Resource::addSearchPaths(const std::string& path)
{
- std::string path(directory);
+ std::vector<std::string> paths;
+ boost::split(paths, path, boost::is_any_of(":"));
- ASSERT(path.length() > 0 && "empty search path string");
+ addSearchPaths(paths);
+}
+
+void Resource::addSearchPaths(const std::vector<std::string>& path)
+{
+ std::vector<std::string>::const_iterator it;
- // add a slash if there isn't one already
- if (*path.rbegin() != '/')
+ for (it = path.begin(); it != path.end(); ++it)
{
- path += '/';
- }
+ std::string onePath(*it);
+
+ ASSERT(!onePath.empty() && "empty search path string");
+
+ // add a slash if there isn't one already
+ if (*onePath.rbegin() != '/')
+ {
+ onePath += '/';
+ }
#if defined(_WIN32) || defined(__WIN32__)
- boost::replace_all(path, "/", "\\");
+ boost::replace_all(onePath, "/", "\\");
#endif
- searchPaths_.push_back(path);
+ gSearchPaths.push_back(onePath);
+ logInfo << "added search path " << onePath << std::endl;
+ }
}
+
std::string Resource::getPath(const std::string& name)
{
std::vector<std::string>::iterator it;
boost::replace_all(path, "/", "\\");
#endif
- for (it = searchPaths_.begin(); it != searchPaths_.end(); ++it)
+ for (it = gSearchPaths.begin(); it != gSearchPaths.end(); ++it)
{
std::string fullPath(*it);
fullPath += path;
* @param directory Path to a directory.
*/
- static void addSearchPath(const std::string& directory);
+ static void addSearchPaths(const std::string& path);
+ static void addSearchPaths(const std::vector<std::string>& path);
/**
* Get the path to a resource of a given name.
private:
- static std::vector<std::string> searchPaths_;
+ static std::vector<std::string> gSearchPaths;
};
*******************************************************************************/
-#include <sstream>
#include <cstdlib> // getenv
#include "Settings.hh"
save();
}
-Settings& Settings::getInstance()
-{
- static Settings settings;
- return settings;
-}
+//Settings& Settings::getInstance()
+//{
+ //static Settings settings;
+ //return settings;
+//}
void Settings::parseArgs(int argc, char* argv[])
}
-void Settings::loadFromFile(const std::string& filePath)
+void Settings::loadFromFiles(const std::string& path)
{
std::vector<std::string> paths;
- boost::split(paths, filePath, boost::is_any_of(":"));
+ boost::split(paths, path, boost::is_any_of(":"));
loadFromFiles(paths);
}
-void Settings::loadFromFiles(const std::vector<std::string>& filePaths)
+void Settings::loadFromFiles(const std::vector<std::string>& path)
{
- std::vector<std::string>::const_iterator it;
-
- char* home = getenv("HOME");
-
- for (it = filePaths.begin(); it != filePaths.end(); ++it)
+ std::vector<std::string> copy(path);
+ std::vector<std::string>::iterator it;
+
+#if defined(_WIN32) || defined(__WIN32__)
+ char* homeDrive = getenv("HOMEDRIVE");
+ char* homePath = getenv("HOMEPATH");
+ std::string home(homeDrive ? homeDrive : "");
+ if (homePath) home += homePath;
+#else
+ char *homePath = getenv("HOME");
+ std::string home(homePath ? homePath : "");
+#endif
+
+ for (it = copy.begin(); it != copy.end(); ++it)
{
- std::string path = *it;
-
- if (home)
+ if (!home.empty())
{
- boost::replace_all(path, "$HOME", home);
+ boost::replace_all(*it, "$HOME", home);
//Mf::logDebug("Copying global settings...");
- //mUserFile = path;
+ //mUserFile = *it;
//mGlobals.pushCopy();
//mScript.set("globals", Script::REGISTRY);
}
- if (mScript.doFile(path) != Script::SUCCESS)
+ if (mScript.doFile(*it) != Script::SUCCESS)
{
std::string str;
mScript[-1].get(str);
}
-void Settings::saveAs(const std::string& filePath)
+void Settings::saveAs(const std::string& path)
{
- mUserFile = filePath;
+ mUserFile = path;
save();
}
}
+Settings settings;
+
+
} // namepsace Mf
/** vim: set ts=4 sw=4 tw=80: *************************************************/
~Settings();
- // get global instance
- static Settings& getInstance();
-
void parseArgs(int argc, char* argv[]);
- void loadFromFile(const std::string& filePath);
- void loadFromFiles(const std::vector<std::string>& filePaths);
+ void loadFromFiles(const std::string& path);
+ void loadFromFiles(const std::vector<std::string>& path);
void clear(); // remove all settings
- void saveAs(const std::string& filePath);
+ void saveAs(const std::string& path);
void save() const;
template <typename T>
}
+extern Settings settings;
+
+
} // namepsace Mf
#endif // _MOOF_SETTINGS_HH_
#include <vorbis/codec.h>
#include <vorbis/vorbisfile.h>
-#include "Engine.hh"
+#include "Core.hh"
+#include "Error.hh"
#include "Library.hh"
#include "Log.hh"
#include "Sound.hh"
{
public:
- Buffer(const std::string& name) :
+ explicit Buffer(const std::string& name) :
Library<Buffer>(name),
mBuffer(-1)
{
std::deque<BufferP> mQueue;
Timer mStreamTimer;
+
+ Backend mBackend;
};
#include <boost/bind.hpp>
#include "Dispatch.hh"
-#include "Engine.hh"
+#include "Core.hh"
#include "Error.hh"
#include "Image.hh"
#include "Library.hh"
#include "Log.hh"
#include "OpenGL.hh"
#include "Texture.hh"
+#include "Video.hh"
namespace Mf {
mWrapT(GL_CLAMP),
mObject(0)
{
- // make sure we have a video
- VideoP video = engine.getVideo();
- ASSERT(video && "cannot load textures without a current video context");
+ // make sure we have a video context
+ //ASSERT(video && "cannot load textures without a current video context");
// we want to know when the GL context is recreated
- mDispatchHandler = engine.addHandler("video.newcontext",
+ mDispatchHandler = core.addHandler("video.newcontext",
boost::bind(&Impl::contextRecreated, this));
loadFromFile();
#include <boost/shared_ptr.hpp>
-#include <Moof/Engine.hh>
+#include <Moof/Core.hh>
#include <Moof/Interpolator.hh>
#include <Moof/Layer.hh>
#include <Moof/Log.hh>
}
- void poppedFromEngine()
+ void removedFromCore()
{
- if (mTo) engine.push(mTo);
+ if (mTo) core.push(mTo);
}
void update(Scalar t, Scalar dt)
if (mInterp.isDone())
{
// to should /replace/ this
- engine.pop(this);
+ core.pop(this);
}
}
*******************************************************************************/
#include "Dispatch.hh"
-#include "Engine.hh"
#include "Error.hh"
#include "Image.hh"
#include "Log.hh"
setCursorVisible(attribs.cursorVisible);
setCursorGrab(attribs.cursorGrab);
setVideoMode(attribs.mode);
+
+ video = this;
}
void Video::recreateContext()
Video::~Video()
{
SDL_FreeSurface(mContext);
+
+ if (video == this) video = 0;
}
// on win32, creating a new context via SDL_SetVideoMode will wipe
// out the GL state, so we gotta notify everyone to reload their
// state after the change
- engine.dispatch("video.newcontext");
-
+ core.dispatch("video.newcontext");
logInfo("video context recreated");
#endif
}
Video::Attributes::Attributes()
{
- // Set some sane GL and window defaults (see SDL_video.c:217)
+ // set some sane GL and window defaults (see SDL_video.c:217)
colorBuffer[0] = 3;
colorBuffer[1] = 3;
colorBuffer[2] = 2;
cursorVisible = true;
cursorGrab = false;
- Settings& settings = Settings::getInstance();
-
std::vector<long> colors;
settings.get("colorbuffers", colors);
if (colors.size() > 0) colorBuffer[0] = colors[0];
}
+Video* video = 0;
+
+
} // namespace Mf
/** vim: set ts=4 sw=4 tw=80: *************************************************/
#include <SDL/SDL.h>
+#include <Moof/Core.hh>
+
namespace Mf {
bool cursorGrab;
Attributes();
+
+ private:
+
+ Backend backend;
};
};
+extern Video* video;
+
+
} // namespace Mf
#endif // _MOOF_VIDEO_HH_
boost::bind(&Impl::drawTile, this, _1));
int detail = 3;
- Mf::Settings::getInstance().get("detail", detail);
+ Mf::settings.get("detail", detail);
script.push(detail); script.set("detail");
script.push(1); script.set("LOW");
*******************************************************************************/
-#include <Moof/Engine.hh>
+#include <Moof/Core.hh>
#include <Moof/OpenGL.hh>
#include <Moof/Transition.hh>
#include "TitleLayer.hh"
-void TitleLayer::pushedOntoEngine()
+void TitleLayer::addedToCore()
{
Mf::Scalar coeff[] = {0.0, 1.0};
mFadeIn.init(coeff, 0.1);
//break;
//}
- Mf::LayerP titleLayer = Mf::engine.pop(this);
- //engine.pushLayer(GameLayer::alloc());
+ Mf::LayerP titleLayer = Mf::core.pop(this);
+ //core.pushLayer(GameLayer::alloc());
Mf::Scalar coeff[] = {0.0, 0.75, 0.99, 1.0};
Mf::PolynomialInterpolator<3> interp(coeff, 0.1);
//Mf::LayerP mGameLayer = GameLayer::alloc();
Mf::Transition<Mf::PolynomialInterpolator<3> >::Ptr transition =
Mf::Transition<Mf::PolynomialInterpolator<3> >::alloc(mGameLayer, titleLayer, interp);
- Mf::engine.push(transition);
+ Mf::core.push(transition);
return true;
}
return TitleLayerP(new TitleLayer);
}
- void pushedOntoEngine();
+ void addedToCore();
void update(Mf::Scalar t, Mf::Scalar dt);
void draw(Mf::Scalar alpha) const;
mkdir -p "$BUILD_DIR"
cp -f "$ROOT_DIR/src/yoink.exe" "$BUILD_DIR"
-"${STRIP:-strip}" "$BUILD_DIR/yoink.exe"
+#"${STRIP:-strip}" "$BUILD_DIR/yoink.exe"
for dll in $DLLS
do
cp -f "@prefix@/bin/$dll.dll" "$BUILD_DIR"
- "${STRIP:-strip}" "BUILD_DIR/$dll.dll"
+ #"${STRIP:-strip}" "BUILD_DIR/$dll.dll"
done
cd "$ROOT_DIR"
exit 1
fi
-rm -rf "$BUILD_DIR"
+#rm -rf "$BUILD_DIR"