finally fixed broken main loop
authorCharles McGarvey <chazmcgarvey@brokenzipper.com>
Wed, 13 Jan 2010 23:36:57 +0000 (16:36 -0700)
committerCharles McGarvey <chazmcgarvey@brokenzipper.com>
Wed, 13 Jan 2010 23:36:57 +0000 (16:36 -0700)
16 files changed:
data/scenes/Classic.lua
data/yoinkrc
doc/yoink.6.in
src/Character.cc
src/ErrorHandler.cc
src/GameLayer.cc
src/Heroine.cc
src/MainLayer.cc
src/Moof/Engine.cc
src/Moof/Engine.hh
src/Moof/Error.hh
src/Moof/Log.cc
src/Moof/Settings.hh
src/Moof/Timer.cc
src/Moof/Timer.hh
src/Moof/Video.cc

index 5709632fc54dfb3b2280375b34204429c299fccf..2ec9e0271a2789f246b128a788414e79e3be4cca 100644 (file)
@@ -757,7 +757,7 @@ DrawTilemap({
 -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 ResetTransform()
-Translate(-0.32, -0.28, -27)
+Translate(-0.3, -0.3, -35)
 Scale(105, 52, 1)
 SetTexture("BackgroundFar")
 DrawTile()
index 79fa707511a9571832dd0e12865063e555504a0a..d7f97ccd00b798ed714351c20fc3cbd74082dc08 100644 (file)
@@ -7,63 +7,67 @@ print "loading default settings..."
 
 -- Set the level of detail to use when drawing scenes.  This can be 1, 2 or
 -- 3, where 1 shows the least amount of detail and 3 draws the scene with
--- the most detail.
+-- the most detail.  Lower levels of detail may improve performance on
+-- slower machines.
 
 detail                 = 3
 
--- Set the number of times each second the physics state will be updated.  A
--- value of 100 or higher is ideal for accurate physics approximations.  Values
--- that are much lower cause the CPU to do less work, but accuracy will suffer.
--- Errors could be introduced in the game with extremely low values.
+-- Set the number of times each second the physics state will be updated.
+-- The quality of the physics simulation will increase as you increase this
+-- value, but the processor will be taxed more.  Errors could be introduced
+-- in the game with extremely low values.
 
 timestep               = 80
 
--- Set the maximum number of frames that can be drawn per second.  A value
--- of 50 is pretty good.  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.
+-- Set the target number of frames that should be drawn per second.  The
+-- smoothness of the animation increases as you increase this value.  You
+-- probably want to set this somewhere in the 25-85 range, depending on how
+-- much work you want your computer to do.  For example, if you're on
+-- battery power, you might prefer 25 which is still reasonably smooth and
+-- will decrease battery drain significantly.  You can also set this to a
+-- very high number to effectively draw as many frames as possible, but
+-- your actual framerate might be limited by the refresh rate of your
+-- display--use the swapcontrol setting to enable or disable this behavior.
+-- You can determine your actual framerate with the showfps option.
 
-maxfps                 = timestep / 2
+framerate              = 50
 
--- Set whether or not to print the current actual framerate to the console.
+-- Set this to print the current actual framerate to the console each
+-- second.
 
-printfps               = false
+showfps                        = true
 
--- Set whether or not the game will run in full-screen mode.  If false, the
--- game will run in a window.
+-- Set this to run the game in full-screen mode.  The default behavior is
+-- to run the game in a window.
 
-fullscreen             = false
+fullscreen             = true
 
--- If the game is running in a window, set whether or not the window will
--- be resizable.
+-- If the game is running in a window, set this to also make the window
+-- resizable.  This has no effective if the fullscreen option is true.
 
 resizable              = true
 
--- Set the resolution or size of the window.  The value is an array with
--- three number elements representing the width, height, and bits per pixel
--- that make up the video mode.  A typical value is 800,600 for a size of
--- 800x600 pixels with millions of colors (the third number is optional).
+-- Set the screen resolution or size of the window.  The value is an array
+-- with three number elements representing the width, height, and bits per
+-- pixel that make up the video mode.  If the fullscreen option is set, the
+-- default behavior is to pick a native resolution.  Otherwise, the game
+-- window will default to 800x600.
 
-videomode              = {800, 600}
+--videomode            = {800, 600}
 
--- Set whether or not the cursor will be visible when you mouse over the
--- display of the game.
+-- Set this to make the cursor remain visible as you mouse over the view of
+-- the game.
 
 showcursor             = true
 
--- Set whether or not the drawing should use two buffers.  This results in
--- a higher quality animation.  You should usually leave this as true.
+-- Set this to use double-buffering to improve animation quality.  You
+-- should usually leave this as true.
 
 doublebuffer   = true
 
--- Set whether or not to sync with the display in order to reduce
--- distortion.
+-- Set this to sync with the refresh rate of your display.  Your framerate
+-- will be limited to the refresh rate, but you may experience fewer ugly
+-- "artifacts" caused by the game animation.
 
 swapcontrol            = true
 
index fd00dad8b91c8a215082d7d68480c217b62bf731..ce90f1dfc38caa7e5221b19da5968f52580e0f10 100644 (file)
@@ -104,12 +104,7 @@ If true, double-buffering will be used to help minimize distortion and
 artifacts caused by the animation of the game.  Otherwise, a single buffer
 will be used.  The default value is true.
 .TP
-.B fullscreen
-If true, the window will capture the display and render the game in full
-screen splendor.  A value of false means the game will run in a window.
-The default value is false.
-.TP
-.B maxfps
+.B framerate
 The maximum 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
@@ -121,9 +116,14 @@ 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.
 .TP
-.B printfps
+.B fullscreen
+If true, the window will capture the display and render the game in full
+screen splendor.  A value of false means the game will run in a window.
+The default value is false.
+.TP
+.B showfps
 If true, the current number of frames being drawn per second will be
-printed to the console.  The default value is false.
+printed to the console every second.  The default value is false.
 .TP
 .B resizable
 If true, the window will be resizable by the window manager.  This option
@@ -150,7 +150,7 @@ need to.
 .SH EXAMPLES
 Here are some examples of typical usage:
 .TP
-$ yoink maxfps=60
+$ yoink framerate=60
 Cap the allowable frame-rate to 60Hz.
 .TP
 $ yoink fullscreen=true
@@ -201,7 +201,7 @@ 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 \fBmaxfps\fP
+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.
 .PP
 If you are having audio problems, you may need to upgrade OpenAL.  Some
index 52a13e63ec38d78178c9f6e9ec259d91b366e47a..9da4344aab361bd369eb26f41f56677eff2a5689 100644 (file)
@@ -43,7 +43,7 @@ public:
        {
                Mf::Vector2 x = state.position - location;
                Mf::Scalar mag = x.length();
-               Mf::Scalar d = 50.0;
+               Mf::Scalar d = 0.0;
 
                // spring:
                //mState.force += -15.0 * x - 1.5 * mState.velocity;
@@ -79,7 +79,7 @@ private:
 
 
 Character::Character(const std::string& name) :
-       tilemap("Particles"),
+       tilemap(name),
        animation(name)
 {
        mState.init();
@@ -89,9 +89,9 @@ Character::Character(const std::string& name) :
 
        // forces
        mState.force = Mf::Vector2(0.0, 0.0);
-       //mState.forces.push_back(SpringForce(Mf::Vector2(500.0, 200.0)));
+       //mState.forces.push_back(SpringForce(Mf::Vector2(20.0, 4.0)));
        mState.forces.push_back(ResistanceForce(2.0));
-       //mState.forces.push_back(Mf::LinearState<2>::GravityForce(-400.0));
+       //mState.forces.push_back(Mf::LinearState<2>::GravityForce(-9.8));
 
        // starting position
        mState.position = Mf::Vector2(5.0, 5.0);
index 07bd6d7d6c1d34330eef9e070ac289cf7e5af0dc..8d0a8d9a1a9cedb1265d2a91385e411f08184541 100644 (file)
@@ -54,6 +54,11 @@ std::string getErrorString(const Mf::Error& error)
                        str += ") could not be found.";
                        return str;
 
+               case Mf::Error::OPENAL_INIT:
+                       str += "The audio library returned an error: ";
+                       str += error.what();
+                       return str;
+
                case Mf::Error::RESOURCE_NOT_FOUND:
                        str += "A required resource (";
                        str += error.what();
index 7a8e98cc32471455749b47cf933df38e816d541c..46c32631aad077b362f9db36bebc7513bd179c10 100644 (file)
@@ -122,7 +122,7 @@ GameLayer::GameLayer() :
                        0.1, Mf::Timer::REPEAT);
 
        mState.heroine = Heroine::alloc();
-       mState.heroine->animation.startSequence("GreenDiamond");
+       mState.heroine->animation.startSequence("FlyDiagonallyUp");
 
        Mf::Scalar a[6] = {0.0, 1.5, -0.5, 3.0, -2.0, 1.0};
        mState.interp.init(a, 5.0, Mf::Interpolator::OSCILLATE);
@@ -155,7 +155,7 @@ void GameLayer::update(Mf::Scalar t, Mf::Scalar dt)
        mState.scene->checkForCollision(*mState.heroine);
 
        mState.camera.setPosition(Mf::Vector3(-mState.heroine->getState().position[0],
-                               -mState.heroine->getState().position[1], -6));
+                               -mState.heroine->getState().position[1], -8));
        //mState.camera.lookAt(Mf::promote(mState.heroine->getState().position));
 
        mRay.point = mState.heroine->getState().position;
@@ -193,9 +193,9 @@ void GameLayer::rayTimer()
        {
                hits.front().normal.normalize();
                mRay.solve(point, hits.front().distance);
-               Mf::logInfo << "scene: d = " << hits.front().distance << std::endl;
-               Mf::logInfo << "       P = " << point << std::endl;
-               Mf::logInfo << "       n = " << hits.front().normal << std::endl;
+               //Mf::logInfo << "scene: d = " << hits.front().distance << std::endl;
+               //Mf::logInfo << "       P = " << point << std::endl;
+               //Mf::logInfo << "       n = " << hits.front().normal << std::endl;
        }
 }
 
@@ -291,7 +291,7 @@ void GameLayer::setProjection()
 
 void GameLayer::setProjection(Mf::Scalar width, Mf::Scalar height)
 {
-       mState.camera.setProjection(cml::rad(60.0), width / height, 1.0, 200.0);
+       mState.camera.setProjection(cml::rad(45.0), width / height, 1.0, 200.0);
 }
 
 
index 5df10319d282bb56fe293500359425ecda98ad76..a70b798e92071e6b34fd495f6b2c2219d6543b3b 100644 (file)
@@ -33,7 +33,7 @@
 
        
 Heroine::Heroine() :
-       Character("Effects") {}
+       Character("Heroine") {}
 
 
 void Heroine::update(Mf::Scalar t, Mf::Scalar dt)
index 568f0cd0ebe84b2185945895692d5045c89c7454..5f097ea9438a5cd8e9bd9cd6b8721b3c0f2e991b 100644 (file)
@@ -142,11 +142,13 @@ void MainLayer::setupGL()
 
        glClearColor(0.0, 0.0, 0.0, 1.0);
 
-       glMatrixMode(GL_PROJECTION);
-       glLoadIdentity();
-       gluPerspective(60.0, 1.33333, 1.0, 2500.0);
+       //glMatrixMode(GL_PROJECTION);
+       //glLoadIdentity();
+       //Mf::Scalar ratio = Mf::engine.getVideo()->getWidth() /
+               //Mf::engine.getVideo()->getHeight();
+       //gluPerspective(60.0, ratio, 1.0, 250.0);
 
-       glMatrixMode(GL_MODELVIEW);
+       //glMatrixMode(GL_MODELVIEW);
 }
 
 void MainLayer::contextRecreated()
@@ -272,16 +274,18 @@ int main(int argc, char* argv[])
 
 
        // make sure the engine started up okay
-       if (Mf::engine.getError().isError())
+       const Mf::Error& error = Mf::engine.getError();
+       if (error.isError())
        {
                Mf::ModalDialog dialog;
                dialog.title = PACKAGE_STRING;
-               dialog.text1 = "Fatal Error";
-               dialog.text2 = getErrorString(Mf::engine.getError());
+               dialog.text1 = "Uh oh!";
+               dialog.text2 = getErrorString(error);
                dialog.type = Mf::ModalDialog::CRITICAL;
                dialog.run();
 
-               return 1;
+               // openal errors are not fatal
+               if (error.code() != Mf::Error::OPENAL_INIT) return 1;
        }
 
 
@@ -333,6 +337,7 @@ int main(int argc, char* argv[])
        Mf::Settings& settings = Mf::Settings::getInstance();
        settings.loadFromFile(configFiles);
        settings.parseArgs(argc, argv);
+       Mf::engine.initWithSettings(settings);
 
        std::string iconFile = Mf::Resource::getPath(PACKAGE".png");
 
index 50711c744c9758cd1a15e965b6166582a5ec35b9..5d703da15d745110a4caa63d938c6fc7890bcde3 100644 (file)
@@ -55,10 +55,9 @@ public:
        Impl() :
                mError(Error::NONE),
                mTimestep(0.01),
-               mPrintFps(false)
+               mFramerate(0.02),
+               mShowFps(false)
        {
-               // first, initialize the libraries
-
 #if defined(_WIN32) || defined(__WIN32__)
                if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) != 0)
 #else
@@ -67,21 +66,21 @@ public:
                {
                        const char* error = SDL_GetError();
                        mError.init(Error::SDL_INIT, error);
-                       //throw Exception(Error::SDL_INIT, error);
+                       return; // fatal
                }
                else
                {
-                       char vdName[128];
-                       SDL_VideoDriverName(vdName, sizeof(vdName));
+                       char name[128];
+                       SDL_VideoDriverName(name, sizeof(name));
                        logInfo << "initialized SDL; using video driver `"
-                                        << vdName << "'" << std::endl;
+                                        << name << "'" << std::endl;
                }
 
                if (FE_Init() != 0)
                {
                        const char* error = FE_GetError();
                        mError.init(Error::FASTEVENTS_INIT, error);
-                       //throw Exception(Error::FASTEVENTS_INIT, error);
+                       return; // fatal
                }
 
                mAlDevice = alcOpenDevice(0);
@@ -89,8 +88,7 @@ public:
                if (!mAlDevice || !mAlContext)
                {
                        const char* error = alcGetString(mAlDevice,alcGetError(mAlDevice));
-                       logError << "error while creating audio context: "
-                                        << error << std::endl;
+                       mError.init(Error::OPENAL_INIT, error);
                }
                else
                {
@@ -99,11 +97,10 @@ public:
                                         << alcGetString(mAlDevice, ALC_DEFAULT_DEVICE_SPECIFIER)
                                         << "'" << std::endl;
                }
+       }
 
-               // now load the settings the engine needs
-
-               Settings& settings = Settings::getInstance();
-
+       bool initWithSettings(const Settings& settings)
+       {
                unsigned randomSeed;
                if (settings.get("rngseed", randomSeed)) srand(randomSeed);
                else srand(time(0));
@@ -112,12 +109,15 @@ public:
                settings.get("timestep", timestep);
                mTimestep = 1.0 / timestep;
 
-               Scalar maxFps = 40.0;
-               settings.get("maxfps", maxFps);
-               mMaxFps = 1.0 / maxFps;
+               Scalar framerate = 40.0;
+               settings.get("framerate", framerate);
+               mFramerate = 1.0 / framerate;
                capFps();
 
-               settings.get("printfps", mPrintFps);
+               mShowFps = false;
+               settings.get("showfps", mShowFps);
+
+               return true;
        }
 
        ~Impl()
@@ -143,81 +143,55 @@ public:
 
        void run()
        {
-               Scalar ticksNow = Timer::getTicks();
-
-               Scalar nextStep = ticksNow;
-               Scalar nextDraw = ticksNow;
-               Scalar nextFpsUpdate = ticksNow + 1.0;
-
                Scalar totalTime = 0.0;
-               Scalar deltaTime = 0.0;
-               Scalar accumulator = mTimestep;
+               Scalar ticks = Timer::getTicks();
+
+               Scalar nextUpdate = ticks;
+               Scalar nextDraw = ticks;
+               Scalar nextSecond = ticks + SCALAR(1.0);
 
                mFps = 0;
-               int frameAccum = 0;
+               int frames = 0;
+
+               const int MAX_FRAMESKIP = 15;
+               const Scalar inverseTimestep = SCALAR(1.0) / mTimestep;
 
                do
                {
-                       Scalar newTicks = Timer::getTicks();
-                       deltaTime = newTicks - ticksNow;
-                       ticksNow = newTicks;
-
-                       // don't slow the animation until 4Hz, which is unplayable anyway
-                       if (deltaTime >= 0.25) deltaTime = 0.25;
-                       accumulator += deltaTime;
-
-                       Timer::fireIfExpired(ticksNow);
+                       Timer::fireIfExpired();
                        dispatchEvents();
 
-                       while (accumulator >= mTimestep)
+                       int i = 0;
+                       while (nextUpdate < Timer::getTicks() && i < MAX_FRAMESKIP)
                        {
-                               update(totalTime, mTimestep);
-
                                totalTime += mTimestep;
-                               accumulator -= mTimestep;
+                               update(totalTime, mTimestep);
 
-                               nextStep += mTimestep;
-                       }
-                       if (ticksNow >= nextStep)
-                       {
-                               nextStep = ticksNow + mTimestep;
+                               nextUpdate += mTimestep;
+                               ++i;
                        }
 
-                       if (ticksNow >= nextDraw)
+                       if (nextDraw < (ticks = Timer::getTicks()))
                        {
-                               frameAccum++;
+                               ++frames;
+                               draw((ticks + mTimestep - nextUpdate) * inverseTimestep);
+                               mVideo->swap();
 
-                               if (ticksNow >= nextFpsUpdate) // determine the actual fps
-                               {
-                                       mFps = frameAccum;
-                                       frameAccum = 0;
+                               nextDraw += mFramerate;
 
-                                       nextFpsUpdate += 1.0;
-                                       if (ticksNow >= nextFpsUpdate)
-                                       {
-                                               nextFpsUpdate = ticksNow + 1.0;
-                                       }
-
-                                       if (mPrintFps)
-                                       {
-                                               logInfo << mFps << " fps" << std::endl;
-                                       }
-                               }
+                               if (mShowFps && nextSecond < ticks)
+                               {
+                                       mFps = frames;
+                                       frames = 0;
 
-                               draw(accumulator / mTimestep);
-                               mVideo->swap();
+                                       logInfo << mFps << " fps" << std::endl;
 
-                               nextDraw += mMaxFps;
-                               if (ticksNow >= nextDraw)
-                               {
-                                       // we missed some scheduled draws, so reset the schedule
-                                       nextDraw = ticksNow + mMaxFps;
+                                       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()), Timer::ACTUAL);
+                       Timer::sleep(0.0);
                }
                while (!mStack.empty());
 
@@ -348,12 +322,12 @@ public:
 
        void capFps()
        {
-               if (mMaxFps < mTimestep)
-               {
-                       logWarning << "capping maximum fps to timestep ("
-                                          << mTimestep << ")" << std::endl;
-                       mMaxFps = mTimestep;
-               }
+               //if (mFramerate < mTimestep)
+               //{
+                       //logWarning << "capping maximum fps to timestep ("
+                                          //<< mTimestep << ")" << std::endl;
+                       //mFramerate = mTimestep;
+               //}
        }
 
 
@@ -369,10 +343,10 @@ public:
        std::list<LayerP>::iterator     mStackIt;
 
        Scalar                                          mTimestep;
-       Scalar                                          mMaxFps;
+       Scalar                                          mFramerate;
 
        int                                                     mFps;
-       bool                                            mPrintFps;
+       bool                                            mShowFps;
 };
 
 
@@ -381,46 +355,34 @@ Engine::Engine() :
        mImpl(new Engine::Impl) {}
 
 
-const Error& Engine::getError() const
+bool Engine::initWithSettings(const Settings& settings)
 {
        // pass through
-       return mImpl->mError;
+       return mImpl->initWithSettings(settings);
 }
 
-
-void Engine::setVideo(VideoP video)
+const Error& Engine::getError() const
 {
        // pass through
-       mImpl->mVideo = video;
-}
-
-VideoP Engine::getVideo() const
-{
-       return mImpl->mVideo;
-}
-
-
-void Engine::setTimestep(int ts)
-{
-       mImpl->mTimestep = 1.0 / Scalar(ts);
-       mImpl->capFps();
+       return mImpl->mError;
 }
 
-int Engine::getTimestep() const
+void Engine::clearError()
 {
-       return int(1.0 / mImpl->mTimestep);
+       // pass through
+       mImpl->mError.init(Error::NONE);
 }
 
 
-void Engine::setMaxFps(int maxFps)
+void Engine::setVideo(VideoP video)
 {
-       mImpl->mMaxFps = 1.0 / Scalar(maxFps);
-       mImpl->capFps();
+       // pass through
+       mImpl->mVideo = video;
 }
 
-int Engine::getMaxFps() const
+VideoP Engine::getVideo() const
 {
-       return int(1.0 / mImpl->mMaxFps);
+       return mImpl->mVideo;
 }
 
 
index 07e982abd9ee4207478d077b8365cedc01897643..28d7fa03eab8119d16a58ca5f2c81ad40da69ad5 100644 (file)
@@ -40,6 +40,9 @@
 namespace Mf {
 
 
+class Settings;
+
+
 /**
  * The engine 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
@@ -55,20 +58,18 @@ public:
 
        Engine();
        ~Engine() {}
+       
+       // 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 setTimestep(int ts);
-       int getTimestep() const;
-
-       void setMaxFps(int maxFps);     // draw rate is always capped at the timestep
-       int getMaxFps() const;
-
        int getFps() const;
 
        void push(LayerP layer);        // push a layer onto the top
index 6dab32ffd07e14e93d8cbad3a6bc0620be5e4f7e..86b8a120bdb1b0635153a8a2190d0e3e1b13ad32 100644 (file)
@@ -43,9 +43,11 @@ public:
 
        enum Code
        {
-               NONE = 0,
+               UNINITIALIZED = -1,                     // -
+               NONE = 0,                                       // -
                ALC_INIT,                                       // description
                FASTEVENTS_INIT,                        // description
+               OPENAL_INIT,                            // description
                FILE_NOT_FOUND,                         // path of missing file
                RESOURCE_NOT_FOUND,                     // name of missing resource
                SCRIPT_ERROR,                           // description
index 980977185e7fdf6b8e9bab0390b2beab19aa3c31..3094642565e96550f1ac3ee434296c80dac9a6d6 100644 (file)
@@ -35,7 +35,7 @@
 namespace Mf {
 
 
-Log::Level Log::gLevel = Log::WARNING;
+Log::Level Log::gLevel = Log::INFO;
 
 
 void Log::setLevel(Level level)
index d31b57dcf763c2fe0d38b1f3f96cc1fa24583223..6cd86291b64bb1be6ed959b7b4d61745495c08e6 100644 (file)
@@ -72,18 +72,18 @@ public:
        void save() const;
 
        template <typename T>
-       bool get(const std::string& key, T& value);
+       bool get(const std::string& key, T& value) const;
 
 private:
 
-       Script                  mScript;
+       mutable Script  mScript;
 
        std::string             mUserFile;
 };
 
 
 template <typename T>
-bool Settings::get(const std::string& key, T& value)
+bool Settings::get(const std::string& key, T& value) const
 {
        Script::Slot top = mScript[-1];
        Script::Slot globals = mScript.getGlobalTable();
index b428f0aade848d1813b9d125b2acd9c238dbd5c1..69d2405622f7031cf134715b053304b39afb5ea2 100644 (file)
@@ -152,6 +152,11 @@ bool Timer::isRepeating() const
 }
 
 
+void Timer::fireIfExpired()
+{
+       fireIfExpired(getTicks());
+}
+
 void Timer::fireIfExpired(Scalar t)
 {
        std::map<unsigned,Timer*>::iterator it;
index b657a5f9632aee158d8b8d5ef4e72d9178979369..246b4b1e0188974ea4dc3b600dd988a2d5bb95d1 100644 (file)
@@ -110,6 +110,7 @@ public:
                return gNextFire;
        }
 
+       static void fireIfExpired();
        static void fireIfExpired(Scalar t);
 
 private:
index 8dab056c645843d391e78868ce9b72a8e1c9b6dc..ba375e10318195cc770bca37552288d64bb6d816 100644 (file)
@@ -355,6 +355,11 @@ Video::Attributes::Attributes()
        }
        settings.get("icon", icon);
 
+       settings.get("fullscreen", fullscreen);
+       settings.get("resizable", resizable);
+       settings.get("showcursor", cursorVisible);
+       settings.get("grab", cursorGrab);
+
        std::vector<long> dimensions;
        settings.get("videomode", dimensions);
        if (dimensions.size() > 1)
@@ -362,12 +367,31 @@ Video::Attributes::Attributes()
                mode[0] = dimensions[0];
                mode[1] = dimensions[1];
        }
-       if (dimensions.size() > 2) mode[2] = dimensions[2];
+       else if (fullscreen)
+       {
+               SDL_Rect** modes = SDL_ListModes(NULL, SDL_FULLSCREEN | SDL_HWSURFACE);
 
-       settings.get("fullscreen", fullscreen);
-       settings.get("resizable", resizable);
-       settings.get("showcursor", cursorVisible);
-       settings.get("grab", cursorGrab);
+               if (modes == (SDL_Rect**)0)
+               {
+                       Mf::logError("no native video mode");
+               }
+               else if (modes == (SDL_Rect**)-1)
+               {
+                       Mf::logWarning("any resolution allowed; choosing default 800x600");
+                       mode[0] = 800;
+                       mode[1] = 600;
+               }
+               else
+               {
+                       while (*(modes + 1)) ++modes; // skip to the last
+
+                       mode[0] = (*modes)->w;
+                       mode[1] = (*modes)->h;
+                       Mf::logInfo << "choosing native resolution "
+                                               << mode[0] << "x" << mode[1] << std::endl;
+               }
+       }
+       if (dimensions.size() > 2) mode[2] = dimensions[2];
 }
 
 
This page took 0.054614 seconds and 4 git commands to generate.