new level-based controllers
authorCharles McGarvey <chazmcgarvey@brokenzipper.com>
Wed, 14 Oct 2009 03:24:26 +0000 (21:24 -0600)
committerCharles McGarvey <chazmcgarvey@brokenzipper.com>
Wed, 14 Oct 2009 03:24:26 +0000 (21:24 -0600)
20 files changed:
configure.ac
cscope.make
data/scenes/Classic.lua
src/GameLayer.cc [new file with mode: 0644]
src/GameLayer.hh [moved from src/YoinkApp.hh with 82% similarity]
src/Hud.cc
src/Hud.hh
src/MainLayer.cc [moved from src/YoinkApp.cc with 50% similarity]
src/MainLayer.hh [new file with mode: 0644]
src/Makefile.am
src/Moof/Engine.cc
src/Moof/Engine.hh
src/Moof/Interpolator.hh
src/Moof/Layer.hh [new file with mode: 0644]
src/Moof/Log.cc
src/Moof/Log.hh
src/Moof/Scene.cc
src/Moof/Scene.hh
src/Moof/Script.hh
src/Moof/Settings.cc

index 7d8d54591f1b6cb7b01b54bdbec439b11351cc13..f7e75b0a2a7ea1295c77ac2e019da35ca36fc38b 100644 (file)
@@ -10,7 +10,7 @@ AC_INIT([Yoink], [0.1], [chaz@dogcows.com], [yoink])
 
 AC_CANONICAL_TARGET
 
-AC_CONFIG_SRCDIR([src/YoinkApp.cc])
+AC_CONFIG_SRCDIR([src/GameLayer.cc])
 AC_CONFIG_MACRO_DIR([m4])
 
 AM_INIT_AUTOMAKE
@@ -153,12 +153,6 @@ AC_DEFINE_UNQUOTED([YOINK_DATADIR], ["$DATADIR"],
                                   [Define to path of game asset directory.])
 
 
-CONFIGFILES="/etc/yoinkrc:\$HOME/.yoinkrc"
-
-AC_DEFINE_UNQUOTED([YOINK_CONFIGFILES], ["$CONFIGFILES"],
-                                  [Define to colon-delimited configuration file paths.])
-
-
 #
 # Split the version number into components.
 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
index 258acca7799c3363a56f9102ef1718f844a84888..990b01c3bb342b7a71321ec2478ec9c326c84b9e 100755 (executable)
@@ -10,5 +10,5 @@ find "$current" \
 
 cd "$current"
 
-#cscope -b -q
+cscope -b -q
 
index 62b8a97045b047790e913392fefe46572e3c3143..4cae26a55966de206ca1b1f7f1950c1554e4f55b 100644 (file)
@@ -57,12 +57,12 @@ MakeTilemap({
 -- Right side
 
 ResetTransform()
-Rotate('y', 90)
+Rotate(Y, 90)
 Translate(0, 0, 5)
 Scale(32)
 MakeTilemap({
        width = 5,
-       surface_type = 'right',
+       surface_type = RIGHT,
        tiles = {
                2,      2,      2,      2,      2,
                0,      0,      0,      0,      0,
@@ -85,12 +85,12 @@ MakeTilemap({
 -- Top
 
 ResetTransform()
-Rotate('x', 90)
+Rotate(X, 90)
 Translate(-5, 15, 0)
 Scale(32)
 MakeTilemap({
        width = 5,
-       surface_type = 'top',
+       surface_type = TOP,
        tiles = {
                3,      3,      3,      3,      3,
                3,      3,      3,      3,      3,
@@ -125,7 +125,7 @@ if detail > 1 then
        -- Right side
 
        ResetTransform()
-       Rotate('y', 90)
+       Rotate(Y, 90)
        Translate(7, 0, 0)
        Scale(32)
        MakeTilemap({
@@ -145,7 +145,7 @@ if detail > 1 then
        -- Top
 
        ResetTransform()
-       Rotate('x', 90)
+       Rotate(X, 90)
        Translate(-2, 8, -6)
        Scale(32)
        MakeTilemap({
@@ -167,13 +167,13 @@ end
 -- Left wall
 
 ResetTransform()
-Rotate('y', -90)
+Rotate(Y, -90)
 Translate(10, 0, 1)
 Scale(32)
 SetTexture("Building")
 MakeTilemap({
        width = 4,
-       surface_type = 'left',
+       surface_type = LEFT,
        tiles = {
                -1,     9,      11,     -1,
                9,      10,     12,     11,
@@ -186,12 +186,12 @@ MakeTilemap({
 -- Right wall
 
 ResetTransform()
-Rotate('y', -90)
+Rotate(Y, -90)
 Translate(13, 0, 1)
 Scale(32)
 MakeTilemap({
        width = 4,
-       surface_type = 'right',
+       surface_type = RIGHT,
        tiles = {
                -1,     9,      11,     -1,
                9,      10,     12,     11,
@@ -218,7 +218,7 @@ MakeTilemap({
 -- Pitched roof
 
 ResetTransform()
-Rotate('x', 135)
+Rotate(X, 135)
 Scale(1, 1.5, 1.5)
 Translate(10, 5, 3)
 Scale(32)
@@ -249,7 +249,7 @@ Translate(10, 4, 3)
 Scale(32)
 MakeTilemap({
        width = 3,
-       surface_type = 'top',
+       surface_type = TOP,
        tiles = {
                -1,     -1,     -1
        }
@@ -261,13 +261,13 @@ MakeTilemap({
 -- Courtyard
 
 ResetTransform()
-Rotate('x', 90)
+Rotate(X, 90)
 Translate(-3, 0, 0)
 Scale(32)
 SetTexture("Scenery")
 MakeTilemap({
        width = 13,
-       surface_type = 'top',
+       surface_type = TOP,
        tiles = {
                1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,
                1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,
@@ -306,7 +306,7 @@ if detail > 2 then
 
        ResetTransform()
        Scale(4, 1, 1)
-       Rotate('y', -90)
+       Rotate(Y, -90)
        Translate(1, -0.5, 1)
        Scale(32)
        MakeBillboard({
@@ -318,7 +318,7 @@ if detail > 2 then
 
        ResetTransform()
        Scale(4, 1, 1)
-       Rotate('y', -90)
+       Rotate(Y, -90)
        Translate(9, -0.5, 1)
        Scale(32)
        MakeBillboard({
@@ -363,7 +363,7 @@ if detail > 1 then
        -- Left wall
 
        ResetTransform()
-       Rotate('y', -90)
+       Rotate(Y, -90)
        Translate(19, 0, -3)
        Scale(32)
        MakeTilemap({
@@ -379,7 +379,7 @@ if detail > 1 then
        -- Right wall
 
        ResetTransform()
-       Rotate('y', -90)
+       Rotate(Y, -90)
        Translate(23, 0, -3)
        Scale(32)
        MakeTilemap({
@@ -395,9 +395,9 @@ if detail > 1 then
        -- Left pitched roof
 
        ResetTransform()
-       Rotate('x', 135)
+       Rotate(X, 135)
        Scale(1, 1.5, 1.5)
-       Rotate('y', -90)
+       Rotate(Y, -90)
        Translate(21, 6, -3)
        Scale(32)
        MakeTilemap({
@@ -411,9 +411,9 @@ if detail > 1 then
        -- Right pitched roof
 
        ResetTransform()
-       Rotate('x', -135)
+       Rotate(X, -135)
        Scale(1, 1.5, 1.5)
-       Rotate('y', -90)
+       Rotate(Y, -90)
        Translate(21, 6, -3)
        Scale(32)
        MakeTilemap({
@@ -427,7 +427,7 @@ if detail > 1 then
        -- Finial
 
        ResetTransform()
-       Rotate('y', -90)
+       Rotate(Y, -90)
        Translate(21, 6, -3)
        Scale(32)
        MakeTilemap({
@@ -444,13 +444,13 @@ end
 -- Ground under house
 
 ResetTransform()
-Rotate('x', 90)
+Rotate(X, 90)
 Translate(10, 0, 0)
 Scale(32)
 SetTexture("Scenery")
 MakeTilemap({
        width = 3,
-       surface_type = 'top',
+       surface_type = TOP,
        tiles = {
                1,      1,      1,
                1,      1,      1,
@@ -465,12 +465,12 @@ MakeTilemap({
 -- Left part of center courtyard
 
 ResetTransform()
-Rotate('x', 90)
+Rotate(X, 90)
 Translate(13, 0, 0)
 Scale(32)
 MakeTilemap({
        width = 8,
-       surface_type = 'top',
+       surface_type = TOP,
        tiles = {
                1,      1,      1,      1,      1,      1,      1,      1,
                1,      1,      1,      1,      1,      1,      1,      1,
@@ -528,7 +528,7 @@ if detail > 2 then
        -- Left grass
 
        ResetTransform()
-       Rotate('y', -90)
+       Rotate(Y, -90)
        Translate(14, -0.5, 1)
        Scale(32)
        MakeTilemap({
@@ -541,7 +541,7 @@ if detail > 2 then
        -- Grass left of house
 
        ResetTransform()
-       Rotate('y', -90)
+       Rotate(Y, -90)
        Translate(18, -0.5, 0)
        Scale(32)
        MakeBillboard({
@@ -552,7 +552,7 @@ if detail > 2 then
        -- Grass right of house
 
        ResetTransform()
-       Rotate('y', -90)
+       Rotate(Y, -90)
        Translate(24, -0.5, 0)
        Scale(32)
        MakeBillboard({
@@ -586,7 +586,7 @@ if detail > 2 then
 
        ResetTransform()
        Scale(2, 1, 1)
-       Rotate('y', -90)
+       Rotate(Y, -90)
        Translate(19, -0.5, 2)
        Scale(32)
        MakeBillboard({
@@ -598,7 +598,7 @@ if detail > 2 then
 
        ResetTransform()
        Scale(2, 1, 1)
-       Rotate('y', -90)
+       Rotate(Y, -90)
        Translate(23, -0.5, 2)
        Scale(32)
        MakeBillboard({
@@ -610,12 +610,12 @@ end
 -- Right part of center courtyard
 
 ResetTransform()
-Rotate('x', 90)
+Rotate(X, 90)
 Translate(21, 0, 0)
 Scale(32)
 MakeTilemap({
        width = 7,
-       surface_type = 'top',
+       surface_type = TOP,
        tiles = {
                1,      1,      1,      1,      1,      0,      0,
                1,      1,      1,      1,      1,      0,      0,
@@ -654,7 +654,7 @@ if detail > 2 then
 
        ResetTransform()
        Scale(2, 1, 1)
-       Rotate('y', -90)
+       Rotate(Y, -90)
        Translate(26, -0.5, 5)
        Scale(32)
        MakeBillboard({
@@ -666,7 +666,7 @@ if detail > 2 then
 
        ResetTransform()
        Scale(2, 1, 1)
-       Rotate('y', -90)
+       Rotate(Y, -90)
        Translate(35, -0.5, 5)
        Scale(32)
        MakeBillboard({
@@ -699,7 +699,7 @@ if detail > 2 then
        -- Extra bit of back grass
 
        ResetTransform()
-       Rotate('y', -90)
+       Rotate(Y, -90)
        Translate(34, -0.5, 0)
        Scale(32)
        MakeBillboard({
@@ -711,12 +711,12 @@ end
 -- Ground around tower block
 
 ResetTransform()
-Rotate('x', 90)
+Rotate(X, 90)
 Translate(28, 0, 4)
 Scale(32)
 MakeTilemap({
        width = 5,
-       surface_type = 'top',
+       surface_type = TOP,
        tiles = {
                0,      0,      0,      0,      0,
                0,      0,      0,      0,      0,
@@ -727,12 +727,12 @@ MakeTilemap({
 -- Rightmost ground
 
 ResetTransform()
-Rotate('x', 90)
+Rotate(X, 90)
 Translate(33, 0, 0)
 Scale(32)
 MakeTilemap({
        width = 10,
-       surface_type = 'top',
+       surface_type = TOP,
        tiles = {
                0,      0,      1,      1,      1,      1,      1,      1,      1,      1,
                0,      0,      1,      1,      1,      1,      1,      1,      1,      1,
@@ -769,12 +769,12 @@ MakeTilemap({
 -- Right side
 
 ResetTransform()
-Rotate('y', 90)
+Rotate(Y, 90)
 Translate(33, 0, 4)
 Scale(32)
 MakeTilemap({
        width = 6,
-       surface_type = 'right',
+       surface_type = RIGHT,
        tiles = {
                2,      2,      2,      2,      2,      2,
                0,      1,      0,      0,      1,      0,
@@ -789,12 +789,12 @@ MakeTilemap({
 -- Left side
 
 ResetTransform()
-Rotate('y', 90)
+Rotate(Y, 90)
 Translate(28, 0, 4)
 Scale(32)
 MakeTilemap({
        width = 6,
-       surface_type = 'left',
+       surface_type = LEFT,
        tiles = {
                2,      2,      2,      2,      2,      2,
                0,      1,      6,      0,      1,      0,
@@ -809,12 +809,12 @@ MakeTilemap({
 -- Top
 
 ResetTransform()
-Rotate('x', 90)
+Rotate(X, 90)
 Translate(28, 7, -2)
 Scale(32)
 MakeTilemap({
        width = 5,
-       surface_type = 'top',
+       surface_type = TOP,
        tiles = {
                3,      3,      3,      3,      3,
                3,      3,      3,      3,      3,
@@ -857,12 +857,12 @@ MakeTilemap({
 -- Left side
 
 ResetTransform()
-Rotate('y', 90)
+Rotate(Y, 90)
 Translate(40, 0, 5)
 Scale(32)
 MakeTilemap({
        width = 5,
-       surface_type = 'left',
+       surface_type = LEFT,
        tiles = {
                2,      2,      2,      2,      2,
                6,      0,      0,      0,      0,
@@ -885,12 +885,12 @@ MakeTilemap({
 -- Top
 
 ResetTransform()
-Rotate('x', 90)
+Rotate(X, 90)
 Translate(40, 15, 0)
 Scale(32)
 MakeTilemap({
        width = 5,
-       surface_type = 'top',
+       surface_type = TOP,
        tiles = {
                3,      3,      3,      3,      3,
                3,      3,      3,      3,      3,
diff --git a/src/GameLayer.cc b/src/GameLayer.cc
new file mode 100644 (file)
index 0000000..dfdadaa
--- /dev/null
@@ -0,0 +1,187 @@
+
+/*******************************************************************************
+
+ 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 <Moof/Engine.hh>
+#include <Moof/Log.hh>
+#include <Moof/Math.hh>
+#include <Moof/OpenGL.hh>
+
+#include "GameLayer.hh"
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+GameLayer::GameLayer() :
+       music("NightFusionIntro"),
+       punchSound("Thump")
+{
+       music.setLooping(true);
+       music.enqueue("NightFusionLoop");
+       music.stream();
+
+       heroine = Character::alloc("RobotTrooper");
+       heroine->getAnimation().startSequence("Run");
+
+       Mf::Scalar a[6] = {0.0, 1.5, -0.5, 3.0, -2.0, 1.0};
+       interp.init(a, 2.0, Mf::Interpolator::OSCILLATE);
+
+       Mf::Scalar b[2] = {1.0, 0.0};
+       fadeIn.init(b, 1.0);
+
+       octree = Mf::loadScene("Classic");
+       heroine->treeNode = octree->insert(heroine);
+
+       camera.setProjection(cml::rad(60.0), 1.33333, 32.0, 2500.0);
+       camera.uploadProjectionToGL();
+}
+
+
+void GameLayer::pushed(Mf::Engine& engine)
+{
+       hud = Hud::alloc();
+       engine.pushLayer(hud);
+}
+
+
+void GameLayer::update(Mf::Scalar t, Mf::Scalar dt)
+{
+       //dt *= 0.7;
+
+       fadeIn.update(dt);
+       camera.update(t, dt);
+       heroine->update(t, dt);
+
+       // reinsert heroine
+       heroine->treeNode = octree->reinsert(heroine, heroine->treeNode);
+       octree->print(heroine->treeNode);
+       
+       //camera.lookAt(heroine->getSphere().point);
+       camera.setPosition(Mf::Vector3(-heroine->current.position[0],
+                               -heroine->current.position[1], -256));
+
+       Mf::Vector3 heroinePosition;
+       Mf::promoteVector(heroinePosition, heroine->current.position);
+       Mf::Sound::setListenerPosition(heroinePosition);
+
+       interp.update(dt);
+       hud->setBar1Progress(interp.getState(dt));
+       hud->setBar2Progress(1.0 - interp.getState(dt));
+}
+
+
+void GameLayer::draw(Mf::Scalar alpha) const
+{
+       glMatrixMode(GL_MODELVIEW);
+       glLoadMatrix(camera.getModelviewMatrix().data());
+
+       // DRAW THE SCENE
+       Mf::Texture::resetBind();
+
+       glEnableClientState(GL_VERTEX_ARRAY);
+       glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+       octree->drawIfVisible(alpha, camera.getFrustum());
+
+       //heroine->draw(alpha);
+       heroine->getAabb().draw();
+
+       // DRAW FADE
+       glEnable(GL_BLEND);
+       glMatrixMode(GL_PROJECTION);
+       glPushMatrix();
+       glLoadIdentity();
+       glMatrixMode(GL_MODELVIEW);
+       glPushMatrix();
+       glLoadIdentity();
+       glColor4f(0.0f, 0.0f, 0.0f, fadeIn.getState(alpha));
+       Mf::Texture::resetBind();
+
+       //glRectf(-1.0f, -1.0f, 1.0f, 1.0f);
+       glBegin(GL_QUADS);
+               glVertex3f(-1.0, -1.0, -0.1);
+               glVertex3f(1.0, -1.0, -0.1);
+               glVertex3f(1.0, 1.0, -0.1);
+               glVertex3f(-1.0, 1.0, -0.1);
+       glEnd();
+
+       glDisable(GL_BLEND);
+
+       glMatrixMode(GL_PROJECTION);
+       glPopMatrix();
+       glMatrixMode(GL_MODELVIEW);
+       glPopMatrix();
+}
+
+bool GameLayer::handleEvent(const Mf::Event& event)
+{
+       switch (event.type)
+       {
+               case SDL_KEYDOWN:
+                       if (event.key.keysym.sym == SDLK_SPACE)
+                       {
+                               heroine->getAnimation().startSequence("Punch");
+                               Mf::logInfo("thump!");
+                               punchSound.play();
+                               return true;
+                       }
+                       else if (event.key.keysym.sym == SDLK_p)
+                       {
+                               music.toggle();
+                               return true;
+                       }
+                       else if (event.key.keysym.sym == SDLK_y)
+                       {
+                               Mf::Engine::getInstance().popLayer();
+                               return true;
+                       }
+
+               case SDL_KEYUP:
+                       heroine->handleEvent(event);
+                       break;
+
+               case SDL_MOUSEMOTION:
+               case SDL_MOUSEBUTTONDOWN:
+                       camera.handleEvent(event);
+                       return true;
+
+               case SDL_VIDEORESIZE:
+                       glViewport(0, 0, event.resize.w, event.resize.h);
+                       camera.setProjection(cml::rad(60.0),
+                               double(event.resize.w) / double(event.resize.h), 32.0, 2500.0);
+                       camera.uploadProjectionToGL();
+                       break;
+       }
+
+       return false;
+}
+
+
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
similarity index 82%
rename from src/YoinkApp.hh
rename to src/GameLayer.hh
index 950d31983002443dd83abe9c3c70d4a57321f1b8..b2df7ef11f3aa3433612fc17ed0fec8b86400152 100644 (file)
 
 *******************************************************************************/
 
-#ifndef _YOINKAPP_HH_
-#define _YOINKAPP_HH_
+#ifndef _GAMELAYER_HH_
+#define _GAMELAYER_HH_
 
 /**
- * @file YoinkApp.hh
+ * @file GameLayer.hh
  * This is the big enchilada.
  */
 
 #include <iostream>
 #include <string>
 
+#include <boost/shared_ptr.hpp>
+
 #include <Moof/Camera.hh>
 #include <Moof/Dispatcher.hh>
-#include <Moof/Engine.hh>
 #include <Moof/Interpolator.hh>
+#include <Moof/Layer.hh>
 #include <Moof/Math.hh>
 #include <Moof/Scene.hh>
 #include <Moof/Sound.hh>
 #include "Hud.hh"
 
 
-class YoinkApp : public Mf::Engine
+class GameLayer;
+typedef boost::shared_ptr<GameLayer> GameLayerP;
+
+class GameLayer : public Mf::Layer
 {
 public:
-       YoinkApp(int argc, char* argv[]);
-       ~YoinkApp();
+       GameLayer();
 
-private:
+       static GameLayerP alloc()
+       {
+               return GameLayerP(new GameLayer);
+       }
+
+       void pushed(Mf::Engine& engine);
        void update(Mf::Scalar t, Mf::Scalar dt);
-       void draw(Mf::Scalar alpha);
-       void handleEvent(const Mf::Event& event);
+       void draw(Mf::Scalar alpha) const;
+       bool handleEvent(const Mf::Event& event);
 
-       /**
-        * Set OpenGL to a state we can know and depend on.
-        */
-       void setupGL();
-       void contextRecreated(const Mf::Notification* note);
+private:
 
        Mf::Sound music;
 
@@ -77,11 +82,11 @@ private:
        Mf::Camera camera;
        Mf::OctreeP octree;
 
-       Hud hud;
+       HudP hud;
 };
 
 
-#endif // _YOINKAPP_HH_
+#endif // _GAMELAYER_HH_
 
 /** vim: set ts=4 sw=4 tw=80: *************************************************/
 
index d5ec7bcd8ebbc7222d30c2073f8184a8d9023abc..c535da5a5808d854899e270d243ecb8c8a7b1302 100644 (file)
@@ -171,6 +171,18 @@ void Hud::draw(Mf::Scalar alpha) const
        glPopMatrix();
 }
 
+bool Hud::handleEvent(Mf::Event& event)
+{
+       switch (event.type)
+       {
+               case SDL_VIDEORESIZE:
+                       resize(event.resize.w, event.resize.h);
+                       break;
+       }
+
+       return false;
+}
+
 
 /** vim: set ts=4 sw=4 tw=80: *************************************************/
 
index 8fec549278514ff98814a9799fb09cee494e7450..966ae43bf54a553ace4aedefe65a98eed98c1d17 100644 (file)
@@ -35,6 +35,7 @@
  */
 
 #include <Moof/Drawable.hh>
+#include <Moof/Layer.hh>
 #include <Moof/Math.hh>
 #include <Moof/Rectangle.hh>
 #include <Moof/Tilemap.hh>
@@ -65,12 +66,20 @@ private:
 };
 
 
-class Hud : public Mf::Drawable
+class Hud;
+typedef boost::shared_ptr<Hud> HudP;
+
+class Hud : public Mf::Layer
 {
 public:
 
        Hud();
 
+       static HudP alloc()
+       {
+               return HudP(new Hud);
+       }
+
        void setBar1Progress(Mf::Scalar progress)
        {
                // pass through
@@ -88,6 +97,7 @@ public:
        void resize(int width, int height);
 
        void draw(Mf::Scalar alpha = 0.0) const;
+       bool handleEvent(Mf::Event& event);
 
 private:
 
similarity index 50%
rename from src/YoinkApp.cc
rename to src/MainLayer.cc
index 8690143d16b7356439849753bff0468ec8575a83..51881a770d0e03d8f6d2846c96542c4a2e265d34 100644 (file)
 #include <iostream>
 #include <string>
 
+#include <Moof/Dispatcher.hh>
 #include <Moof/Exception.hh>
 #include <Moof/Log.hh>
-#include <Moof/Math.hh>
 #include <Moof/OpenGL.hh>
-#include <Moof/Settings.hh>
-#include <Moof/Thread.hh>
-#include <Moof/Timer.hh>
+#include <Moof/Resource.hh>
 #include <Moof/Video.hh>
 
-#include "YoinkApp.hh"
+#include "GameLayer.hh"
+#include "MainLayer.hh"
 
 #if HAVE_CONFIG_H
 #include "config.h"
 #endif
 
 
-static std::string configFiles()
+MainLayer::MainLayer()
 {
-       std::string files;
-
-       // look in the configured data directory last of all
-       char* dataDir = getenv("YOINK_DATADIR");
-       files += (dataDir ? dataDir : YOINK_DATADIR);
-       files += "/yoinkrc";
-
-       // add the colon-delimited paths from configure
-       files += ":";
-       files += YOINK_CONFIGFILES;
-
-       char* configFile = getenv("YOINKRC");
-       if (configFile)
-       {
-               // if a config file from the environment variable is specified, we want
-               // to load it first so it has precedence
-               files += ":";
-               files += configFile;
-       }
-
-       return files;
+       Mf::dispatcher::addHandler("video.context_recreated",
+                       boost::bind(&MainLayer::contextRecreated, this, _1), this);
+       setupGL();
 }
 
-static std::string iconFile()
+MainLayer::~MainLayer()
 {
-       char* dataDir = getenv("YOINK_DATADIR");
-
-       // first set up the search paths so we can find the icon and other resources
-       if (dataDir)
-       {
-               // look first in the data directory specified by the environment
-               Mf::Resource::addSearchPath(dataDir);
-       }
-
-       // then look in the configured data directory
-       Mf::Resource::addSearchPath(YOINK_DATADIR);
-
-       return Mf::Resource::getPath("yoink.png");
+       Mf::dispatcher::removeHandler(this);
 }
 
 
-YoinkApp::YoinkApp(int argc, char* argv[]) :
-       Mf::Engine(argc, argv, configFiles(), PACKAGE_STRING, iconFile()),
-       music("NightFusionIntro"),
-       punchSound("RobotPunch")
+void MainLayer::pushed(Mf::Engine& e)
 {
-       Mf::dispatcher::addHandler("video.context_recreated",
-                       boost::bind(&YoinkApp::contextRecreated, this, _1), this);
-       setupGL();
-
-       music.setLooping(true);
-       music.enqueue("NightFusionLoop");
-       music.stream();
-
-       heroine = Character::alloc("RobotTrooper");
-       heroine->getAnimation().startSequence("Run");
-
-       Mf::Scalar a[6] = {0.0, 1.5, -0.5, 3.0, -2.0, 1.0};
-       interp.init(a, 2.0, Mf::Interpolator::OSCILLATE);
+       engine = &e;
+       engine->pushLayer(GameLayer::alloc());
+}
 
-       Mf::Scalar b[2] = {1.0, 0.0};
-       fadeIn.init(b, 1.0);
 
-       octree = Mf::loadScene("Classic");
-       heroine->treeNode = octree->insert(heroine);
+void MainLayer::draw(Mf::Scalar alpha) const
+{
+       glClear(GL_DEPTH_BUFFER_BIT);
 }
 
-YoinkApp::~YoinkApp()
+bool MainLayer::handleEvent(const Mf::Event& event)
 {
-       Mf::dispatcher::removeHandler(this);
+       switch (event.type)
+       {
+               case SDL_KEYDOWN:
+                       if (event.key.keysym.sym == SDLK_ESCAPE)
+                       {
+                               engine->clearLayers();
+                       }
+                       else if (event.key.keysym.sym == SDLK_f)
+                       {
+                               engine->getVideo().toggleFull();
+                       }
+                       else if (event.key.keysym.sym == SDLK_l)
+                       {
+                               Mf::Video& video = engine->getVideo();
+                               video.toggleCursorGrab();
+                               video.toggleCursorVisible();
+                       }
+                       else if (event.key.keysym.sym == SDLK_y)
+                       {
+                               engine->pushLayer(GameLayer::alloc());
+                       }
+                       break;
+
+               case SDL_QUIT:
+                       engine->clearLayers();
+                       break;
+       }
+
+       return false;
 }
 
 
-void YoinkApp::setupGL()
+void MainLayer::setupGL()
 {
        glEnable(GL_TEXTURE_2D);
 
@@ -146,155 +129,20 @@ void YoinkApp::setupGL()
        //glMatrixMode(GL_PROJECTION);
        //glLoadIdentity();
        //gluPerspective(60.0, 1.33333, 1.0, 2500.0);
-       camera.setProjection(cml::rad(60.0), 1.33333, 32.0, 2500.0);
-       camera.uploadProjectionToGL();
 
        //glMatrixMode(GL_MODELVIEW);
        
        //glLineWidth(10.0f);
 }
 
-void YoinkApp::contextRecreated(const Mf::Notification* note)
+void MainLayer::contextRecreated(const Mf::Notification* note)
 {
-       // 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.
+       // 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
        setupGL();
 }
 
 
-void YoinkApp::update(Mf::Scalar t, Mf::Scalar dt)
-{
-       //dt *= 0.7;
-
-       fadeIn.update(dt);
-       camera.update(t, dt);
-       heroine->update(t, dt);
-
-       // reinsert heroine
-       heroine->treeNode = octree->reinsert(heroine, heroine->treeNode);
-       octree->print(heroine->treeNode);
-       
-       //camera.lookAt(heroine->getSphere().point);
-       camera.setPosition(Mf::Vector3(-heroine->current.position[0],
-                               -heroine->current.position[1], -256));
-
-       Mf::Vector3 heroinePosition;
-       Mf::promoteVector(heroinePosition, heroine->current.position);
-       Mf::Sound::setListenerPosition(heroinePosition);
-
-       interp.update(dt);
-       hud.setBar1Progress(interp.getState(dt));
-       hud.setBar2Progress(1.0 - interp.getState(dt));
-}
-
-
-void YoinkApp::draw(Mf::Scalar alpha)
-{
-       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
-       glMatrixMode(GL_MODELVIEW);
-       glLoadMatrix(camera.getModelviewMatrix().data());
-
-       // DRAW THE SCENE
-       Mf::Texture::resetBind();
-
-       glEnableClientState(GL_VERTEX_ARRAY);
-       glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-
-       octree->drawIfVisible(alpha, camera.getFrustum());
-
-       //heroine->draw(alpha);
-       heroine->getAabb().draw();
-
-       hud.draw();
-
-       // DRAW FADE
-       glEnable(GL_BLEND);
-       glMatrixMode(GL_PROJECTION);
-       glPushMatrix();
-       glLoadIdentity();
-       glMatrixMode(GL_MODELVIEW);
-       glPushMatrix();
-       glLoadIdentity();
-       glColor4f(0.0f, 0.0f, 0.0f, fadeIn.getState(alpha));
-       Mf::Texture::resetBind();
-
-       //glRectf(-1.0f, -1.0f, 1.0f, 1.0f);
-       glBegin(GL_QUADS);
-               glVertex3f(-1.0, -1.0, -0.1);
-               glVertex3f(1.0, -1.0, -0.1);
-               glVertex3f(1.0, 1.0, -0.1);
-               glVertex3f(-1.0, 1.0, -0.1);
-       glEnd();
-
-       glDisable(GL_BLEND);
-
-       glMatrixMode(GL_PROJECTION);
-       glPopMatrix();
-       glMatrixMode(GL_MODELVIEW);
-       glPopMatrix();
-}
-
-void YoinkApp::handleEvent(const Mf::Event& event)
-{
-       switch (event.type)
-       {
-               case SDL_KEYDOWN:
-                       if (event.key.keysym.sym == SDLK_ESCAPE)
-                       {
-                               stop();
-                               break;
-                       }
-                       else if (event.key.keysym.sym == SDLK_f)
-                       {
-                               getVideo().toggleFull();
-                               break;
-                       }
-                       else if (event.key.keysym.sym == SDLK_SPACE)
-                       {
-                               heroine->getAnimation().startSequence("Punch");
-                               punchSound.play();
-                               break;
-                       }
-                       else if (event.key.keysym.sym == SDLK_t)
-                       {
-                               Mf::dispatcher::dispatch("video.context_recreated");
-                               break;
-                       }
-                       else if (event.key.keysym.sym == SDLK_p)
-                       {
-                               music.toggle();
-                               break;
-                       }
-                       else if (event.key.keysym.sym == SDLK_l)
-                       {
-                               getVideo().toggleCursorGrab();
-                               getVideo().toggleCursorVisible();
-                               break;
-                       }
-
-               case SDL_KEYUP:
-                       heroine->handleEvent(event);
-
-               case SDL_MOUSEMOTION:
-               case SDL_MOUSEBUTTONDOWN:
-                       camera.handleEvent(event);
-                       break;
-
-               case SDL_QUIT:
-                       stop();
-                       break;
-
-               case SDL_VIDEORESIZE:
-                       glViewport(0, 0, event.resize.w, event.resize.h);
-                       hud.resize(event.resize.w, event.resize.h);
-                       camera.setProjection(cml::rad(60.0),
-                               double(event.resize.w) / double(event.resize.h), 32.0, 2500.0);
-                       camera.uploadProjectionToGL();
-                       break;
-       }
-}
-
 
 void printUsage()
 {
@@ -328,6 +176,7 @@ int main(int argc, char* argv[])
                          << "Send patches and bug reports to <"
                          PACKAGE_BUGREPORT << ">." << std::endl << std::endl;
 
+
 #if            YOINK_LOGLEVEL >= 4
        Mf::setLogLevel(Mf::LOG_DEBUG);
 #elif  YOINK_LOGLEVEL >= 3
@@ -340,23 +189,57 @@ int main(int argc, char* argv[])
        Mf::setLogLevel(Mf::LOG_NONE);
 #endif
 
-       int status = 0;
+
+       // 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);
+
+       std::string iconFile = Mf::Resource::getPath("yoink.png");
+
+
+       // Build the list of config files to search for, in this order:
+       // 1. YOINK_DATADIR/yoinkrc
+       // 2. /etc/yoinkrc
+       // 3. $HOME/.yoinkrc
+       // 4. YOINKRC (environment)
+
+       std::string configFiles;
+
+       configFiles += Mf::Resource::getPath("yoinkrc");
+       configFiles += ":/etc/yoinkrc:$HOME/.yoinkrc";
+
+       char* configFile = getenv("YOINKRC");
+       if (configFile)
+       {
+               configFiles += ":";
+               configFiles += configFile;
+       }
+
 
        try
        {
-               YoinkApp app(argc, argv);
-               status = app.run();
+               Mf::Engine app(argc, argv, PACKAGE_STRING, iconFile, configFiles);
+               app.pushLayer(MainLayer::alloc());
+
+               app.run();
        }
        catch (Mf::Exception e)
        {
                Mf::logError("unhandled exception: <<%s>>", e.what());
                Mf::logInfo("it's time to crash now :-(");
-               //status = 1;
                throw e;
        }
 
        std::cout << std::endl << "Goodbye..." << std::endl << std::endl;
-       return status;
+       return 0;
 }
 
 
diff --git a/src/MainLayer.hh b/src/MainLayer.hh
new file mode 100644 (file)
index 0000000..db529a1
--- /dev/null
@@ -0,0 +1,80 @@
+
+/*******************************************************************************
+
+ 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.
+
+*******************************************************************************/
+
+#ifndef _MAINLAYER_HH_
+#define _MAINLAYER_HH_
+
+/**
+ * @file MainLayer.hh
+ * This is where all the fun begins.
+ */
+
+#include <iostream>
+#include <string>
+
+#include <boost/shared_ptr.hpp>
+
+#include <Moof/Engine.hh>
+#include <Moof/Layer.hh>
+#include <Moof/Math.hh>
+
+
+class MainLayer;
+typedef boost::shared_ptr<MainLayer> MainLayerP;
+
+struct MainLayer : public Mf::Layer
+{
+       MainLayer();
+       ~MainLayer();
+
+       static MainLayerP alloc()
+       {
+               return MainLayerP(new MainLayer);
+       }
+
+       void pushed(Mf::Engine& engine);
+
+       void draw(Mf::Scalar alpha) const;
+       bool handleEvent(const Mf::Event& event);
+
+private:
+
+       /**
+        * Set OpenGL to a state we can know and depend on.
+        */
+       void setupGL();
+       void contextRecreated(const Mf::Notification* note);
+
+       Mf::Engine* engine;
+};
+
+
+#endif // _MAINLAYER_HH_
+
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
index 80372e2487f91a01fc5b96c17d35d64fbb348768..ff318048071729560a868139f5663ef688b64c44 100644 (file)
@@ -36,6 +36,7 @@ libmoof_a_SOURCES = \
                                        Moof/Hash.cc \
                                        Moof/Hash.hh \
                                        Moof/Interpolator.hh \
+                                       Moof/Layer.hh \
                                        Moof/Log.cc \
                                        Moof/Log.hh \
                                        Moof/Math.hh \
@@ -110,14 +111,16 @@ bin_PROGRAMS = yoink
 yoink_SOURCES = \
                                Character.cc \
                                Character.hh \
+                               GameLayer.cc \
+                               GameLayer.hh \
                                Hud.cc \
                                Hud.hh \
+                               MainLayer.cc \
+                               MainLayer.hh \
                                TilemapFont.cc \
                                TilemapFont.hh \
                                Typesetter.cc \
                                Typesetter.hh \
-                               YoinkApp.cc \
-                               YoinkApp.hh \
                                $(ENDLIST)
 
 if WIN32
index 18ce5d7e5f8c6d0b4664da080b16ba1ad2623ace..5bfaaf3cd8d715d0927c9a284a5199a6686e98a6 100644 (file)
@@ -26,7 +26,9 @@
 
 *******************************************************************************/
 
+#include <algorithm>
 #include <cstdlib>                     // exit
+#include <list>
 #include <string>
 
 #include <SDL/SDL.h>
@@ -35,6 +37,7 @@
 
 #include "Dispatcher.hh"
 #include "Engine.hh"
+#include "Event.hh"
 #include "Log.hh"
 #include "Random.hh"
 #include "Settings.hh"
@@ -48,10 +51,10 @@ namespace Mf {
 class Engine::Impl
 {
 public:
-       Impl(int argc, char* argv[], const std::string& configFile,
-                       const std::string& name, const std::string& iconFile,
-                       Engine* outer) :
-               interface(outer),
+       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)
        {
@@ -109,7 +112,7 @@ public:
         * the exit code used to stop the loop.
         */
 
-       int run()
+       void run()
        {
                Scalar ticksNow = Timer::getTicks();
 
@@ -124,7 +127,6 @@ public:
                fps = 0;
                int frameAccum = 0;
 
-               running = true;
                do
                {
                        Scalar newTicks = Timer::getTicks();
@@ -139,7 +141,7 @@ public:
                        while (accumulator >= timestep)
                        {
                                dispatchEvents();
-                               interface->update(totalTime, timestep);
+                               update(totalTime, timestep);
 
                                totalTime += timestep;
                                accumulator -= timestep;
@@ -172,7 +174,7 @@ public:
                                        }
                                }
 
-                               interface->draw(accumulator / timestep);
+                               draw(accumulator / timestep);
                                video->swap();
 
                                nextDraw += drawRate;
@@ -187,12 +189,9 @@ public:
                        Timer::sleep(std::min(std::min(nextStep, nextDraw),
                                                Timer::getNextFire()), true);
                }
-               while (running);
-
-               return exitCode;
+               while (!stack.empty());
        }
 
-
        void dispatchEvents()
        {
                SDL_Event event;
@@ -205,7 +204,8 @@ public:
                                        if (event.key.keysym.sym == SDLK_ESCAPE &&
                                                        (SDL_GetModState() & KMOD_CTRL) )
                                        {
-                                          exit(0);
+                                               // emergency escape
+                                               exit(0);
                                        }
                                        break;
 
@@ -214,51 +214,133 @@ public:
                                        break;
                        }
 
-                       interface->handleEvent(event);
+                       handleEvent(event);
                }
        }
 
 
-       Engine*         interface;
+       void update(Scalar t, Scalar dt)
+       {
+               for (stackIt = stack.begin(); stackIt != stack.end(); ++stackIt)
+               {
+                       (*stackIt)->update(t, dt);
+               }
+       }
 
-       VideoP          video;
+       void draw(Scalar alpha)
+       {
+               // FIXME - this will crash if the layer being drawn pops itself
+               std::list<LayerP>::reverse_iterator it;
+               for (it = stack.rbegin(); it != stack.rend(); ++it)
+               {
+                       (*it)->draw(alpha);
+               }
+       }
 
-       bool            running;
-       int                     exitCode;
+       void handleEvent(const Event& event)
+       {
+               for (stackIt = stack.begin(); stackIt != stack.end(); ++stackIt)
+               {
+                       if ((*stackIt)->handleEvent(event)) break;
+               }
+       }
 
-       Scalar          timestep;
-       Scalar          drawRate;
 
-       long            fps;
-       bool            printFps;
-};
+       void pushLayer(LayerP layer)
+       {
+               ASSERT(layer && "cannot push null layer");
+               stack.push_front(layer);
+               layer->pushed(interface);
+       }
+
+       void popLayer()
+       {
+               bool fixIt = false;
+               if (stack.begin() == stackIt) fixIt = true;
 
+               LayerP popped = stack.front();
+               stack.pop_front();
+               popped->popped(interface);
 
-Engine::Engine(int argc, char* argv[], const std::string& configFile,
-               const std::string& name, const std::string& iconFile) :
-       impl_(new Engine::Impl(argc, argv, configFile, name, iconFile, this)) {}
+               if (fixIt) stackIt = --stack.begin();
+       }
+
+       void popLayer(Layer* layer)
+       {
+               bool fixIt = false;
 
-Engine::~Engine() {}
+               std::list<LayerP>::iterator it;
+               for (it = stack.begin(); it != stack.end(); ++it)
+               {
+                       if (it == stackIt) fixIt = true;
 
+                       if ((*it).get() == layer)
+                       {
+                               ++it;
+                               do
+                               {
+                                       LayerP popped = stack.front();
+                                       stack.pop_front();
+                                       popped->popped(interface);
+                               }
+                               while (stack.begin() != it);
+
+                               if (fixIt) stackIt = --stack.begin();
+                               return;
+                       }
+               }
+       }
 
-int Engine::run()
+       void clearLayers()
+       {
+               stack.clear();
+               stackIt = stack.begin();
+       }
+
+
+       Engine&                         interface;
+
+       VideoP                          video;
+
+       std::list<LayerP>                       stack;
+       std::list<LayerP>::iterator     stackIt;
+
+       Scalar                          timestep;
+       Scalar                          drawRate;
+
+       long                            fps;
+       bool                            printFps;
+};
+
+
+static Engine* instance = 0;
+
+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))
 {
-       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;
 }
 
 
+void Engine::run()
+{
+       return impl_->run();
+}
+
 void Engine::setTimestep(Scalar ts)
 {
        impl_->timestep = ts;
 }
 
-Scalar Engine::getTimestep()
+Scalar Engine::getTimestep() const
 {
        return impl_->timestep;
 }
@@ -268,26 +350,46 @@ void Engine::setMaxFrameRate(long maxFps)
        impl_->drawRate = 1.0 / Scalar(maxFps);
 }
 
-long Engine::getMaxFrameRate()
+long Engine::getMaxFrameRate() const
 {
        return long(1.0 / impl_->drawRate);
 }
 
 
-Video& Engine::getVideo()
+Video& Engine::getVideo() const
 {
        return *impl_->video;
 }
 
-long Engine::getFrameRate()
+long Engine::getFrameRate() const
 {
        return impl_->fps;
 }
 
 
-void Engine::update(Scalar t, Scalar dt) {}
-void Engine::draw(Scalar alpha) {}
-void Engine::handleEvent(const Event& event) {}
+void Engine::pushLayer(LayerP layer)
+{
+       // pass through
+       impl_->pushLayer(layer);
+}
+
+void Engine::popLayer()
+{
+       // pass through
+       impl_->popLayer();
+}
+
+void Engine::popLayer(Layer* layer)
+{
+       // pass through
+       impl_->popLayer(layer);
+}
+
+void Engine::clearLayers()
+{
+       // pass through
+       impl_->clearLayers();
+}
 
 
 } // namespace Mf
index 0617b1a5c3094025331233fe4c8ced0a5742010e..a0c23002080ff5ef65fa1a336cedd1294e101a35 100644 (file)
 #ifndef _MOOF_ENGINE_HH_
 #define _MOOF_ENGINE_HH_
 
-#include <stdexcept>
-
 #include <boost/shared_ptr.hpp>
 
-#include <Moof/Event.hh>
 #include <Moof/Exception.hh>
+#include <Moof/Layer.hh>
 #include <Moof/Math.hh>
 
 
 namespace Mf {
 
 
-// forward declaration
+// forward declarations
 class Video;
 
-class Engine
+struct Engine
 {
-protected:
-
-       Engine(int argc, char* argv[], const std::string& configFile,
-                       const std::string& name, const std::string& iconFile);
+       Engine(int argc, char* argv[], const std::string& name, 
+                       const std::string& iconFile, const std::string& configFile);
+       ~Engine() {}
 
-public:
+       // get global instance
+       static Engine& getInstance();
 
-       virtual ~Engine();
-
-       int run();
-       void stop(int exitCode = 0);
+       void run();
 
        void setTimestep(Scalar ts);
-       Scalar getTimestep();
+       Scalar getTimestep() const;
        void setMaxFrameRate(long maxFps);
-       long getMaxFrameRate();
+       long getMaxFrameRate() const;
 
-       Video& getVideo();
-       long getFrameRate();
+       Video& getVideo() const;
+       long getFrameRate() const;
 
-       // override these if you want
-       virtual void update(Scalar t, Scalar dt);
-       virtual void draw(Scalar alpha);
-       virtual void handleEvent(const Event& event);
+       void pushLayer(LayerP layer);
+       void popLayer();
+       void popLayer(Layer* layer);
+       void clearLayers();
 
        struct Exception : public Mf::Exception
        {
@@ -83,8 +78,6 @@ public:
        };
 
 private:
-       Engine() {} // this class must be subclassed to be useful
-
        class Impl;
        boost::shared_ptr<Impl> impl_;
 };
index b32482c73a9e502667530293786db06f04b4d60a..7ded928d8c3109d78fa29a3ff3d4386272b94cc9 100644 (file)
@@ -139,12 +139,12 @@ public:
 
        virtual void calculate(T& value, Scalar alpha) = 0;
 
-       const T& getValue()
+       const T& getValue() const
        {
                return value_;
        }
 
-       const T getState(Scalar alpha)
+       const T getState(Scalar alpha) const
        {
                return cml::lerp(previous_, value_, alpha);
        }
diff --git a/src/Moof/Layer.hh b/src/Moof/Layer.hh
new file mode 100644 (file)
index 0000000..8ec678d
--- /dev/null
@@ -0,0 +1,66 @@
+
+/*******************************************************************************
+
+ 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.
+
+*******************************************************************************/
+
+#ifndef _MOOF_LAYER_HH_
+#define _MOOF_LAYER_HH_
+
+#include <boost/shared_ptr.hpp>
+
+#include <Moof/Drawable.hh>
+#include <Moof/Event.hh>
+#include <Moof/Math.hh>
+
+
+namespace Mf {
+
+
+// forward declaration
+class Engine;
+
+
+struct Layer : public Drawable
+{
+       virtual ~Layer() {}
+
+       virtual void pushed(Engine& engine) {}
+       virtual void popped(Engine& engine) {}
+
+       virtual void update(Scalar t, Scalar dt) {}
+       virtual void draw(Scalar alpha) const {}
+       virtual bool handleEvent(const Event& event) { return false; }
+};
+
+typedef boost::shared_ptr<Layer> LayerP;
+
+
+} // namespace Mf
+
+#endif // _MOOF_LAYER_HH_
+
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+
index 96c70955da1231d9d687260f75698ba5d9c74f74..96827e1a8be84a9219bbb47e1569f195af82f6eb 100644 (file)
@@ -116,7 +116,7 @@ void logDebug(const char* fmt, ...)
        va_end(args);
 }
 
-static void logScript(const char* fmt, ...)
+void logScript(const char* fmt, ...)
 {
        va_list args;
        va_start(args, fmt);
index 09130ed5010aeb535eef7abc09802d959494c98e..1f9d0c6b084d9a6f404f3ec756d7c6eb9418c9c2 100644 (file)
@@ -114,6 +114,7 @@ void logInfo(const char* fmt, ...);
 
 void logDebug(const char* fmt, ...);
 
+void logScript(const char* fmt, ...);
 class Script;
 int logScript(Script& script);
 void importLogScript(Script& script);
index fe49ed276d8706edc8626b566db7db51dd108dd8..b3313124d22100bb4e59871ca8d4e3070d290987 100644 (file)
@@ -56,6 +56,13 @@ struct Meh
 
        OctreeP         octree;
 
+       enum AXIS
+       {
+               X = 0,
+               Y = 1,
+               Z = 2
+       };
+
        Meh()
        {
                octree = Octree::alloc(Aabb());
@@ -112,15 +119,9 @@ struct Meh
 
        int translate(Script& script)
        {
-               Script::Value x = script[1];
-               Script::Value y = script[2];
-               Script::Value z = script[3];
-
-               if (!x.isNumber() || !y.isNumber() || !z.isNumber())
-               {
-                       logWarning("wrong arguments to translate; ignoring...");
-                       return 0;
-               }
+               Script::Value x = script[1].requireNumber();
+               Script::Value y = script[2].requireNumber();
+               Script::Value z = script[3].requireNumber();
 
                Vector3 vec;
                x.get(vec[0]);
@@ -139,9 +140,9 @@ struct Meh
                if (script.getSize() == 3)
                {
                        Vector3 vec;
-                       script[1].get(vec[0]);
-                       script[2].get(vec[1]);
-                       script[3].get(vec[2]);
+                       script[1].requireNumber().get(vec[0]);
+                       script[2].requireNumber().get(vec[1]);
+                       script[3].requireNumber().get(vec[2]);
 
                        Matrix4 scaling;
                        cml::matrix_scale(scaling, vec);
@@ -150,16 +151,15 @@ struct Meh
                else if (script.getSize() == 1)
                {
                        Scalar value = 1.0;
-                       script[1].get(value);
+                       script[1].requireNumber().get(value);
 
                        Matrix4 scaling;
-                       cml::matrix_uniform_scale(scaling,
-                                       Scalar(value));
+                       cml::matrix_uniform_scale(scaling, value);
                        transform = scaling * transform;
                }
                else
                {
-                       logWarning("wrong arguments to scale; ignoring...");
+                       script.getTop().throwError("wrong number of arguments");
                }
 
                return 0;
@@ -167,53 +167,34 @@ struct Meh
 
        int rotate(Script& script)
        {
-               Script::Value a = script[1];
-               Script::Value d = script[2];
-
-               if (!a.isString() || !d.isNumber())
-               {
-                       logWarning("wrong arguments to rotate; ignoring...");
-                       return 0;
-               }
-
-               std::string axis;
-               a.get(axis);
+               Script::Value axis = script[1].requireString();
+               Script::Value angle = script[2].requireNumber();
 
                size_t index = 0;
-               if (axis == "x")      index = 0;
-               else if (axis == "y") index = 1;
-               else if (axis == "z") index = 2;
+               axis.get(index);
 
                Scalar value;
-               d.get(value);
+               angle.get(value);
 
-               cml::matrix_rotate_about_world_axis(transform,
-                               index, cml::rad(Scalar(value)));
+               cml::matrix_rotate_about_world_axis(transform, index, cml::rad(value));
 
                return 0;
        }
 
        int setTexture(Script& script)
        {
-               Script::Value t = script[1];
+               Script::Value name = script[1].requireString();
 
-               if (t.isString()) t.get(texture);
-               else logWarning("wrong arguments to setTexture; ignoring...");
+               name.get(texture);
 
                return 0;
        }
 
        int makeTilemap(Script& script)
        {
-               Script::Value table = script[1];
+               Script::Value table = script[1].requireTable();
                Script::Value top = script[-1];
 
-               if (!table.isTable())
-               {
-                       logWarning("wrong arguments to makeTilemap; ignoring...");
-                       return 0;
-               }
-
                long width = 1;
                long height = 1;
 
@@ -226,43 +207,37 @@ struct Meh
                Script::Value tiles = script.getTop();
                nTiles = tiles.getLength();
 
-               std::vector< std::vector<Tilemap::Index> > indices;
+               if (nTiles % width != 0) table.throwError("invalid number of tiles");
 
-               if (nTiles % width == 0)
-               {
-                       int i, w, h;
+               std::vector< std::vector<Tilemap::Index> > indices;
 
-                       height = nTiles / width;
-                       indices.resize(height);
+               int i, w, h;
 
-                       // the indices are stored upside-down in the scene file so that they
-                       // are easier to edit as text, so we'll need to load them last row
-                       // first
+               height = nTiles / width;
+               indices.resize(height);
 
-                       i = 1;
-                       for (h = height - 1; h >= 0; --h)
-                       {
-                               std::vector<Tilemap::Index> row;
+               // the indices are stored upside-down in the scene file so that they
+               // are easier to edit as text, so we'll need to load them last row
+               // first
 
-                               for (w = 0; w < width; ++w, ++i)
-                               {
-                                       script.checkStack(2);
-                                       script.push(long(i));
-                                       tiles.pushField();
+               i = 1;
+               for (h = height - 1; h >= 0; --h)
+               {
+                       std::vector<Tilemap::Index> row;
 
-                                       long index;
-                                       top.get(index);
+                       for (w = 0; w < width; ++w, ++i)
+                       {
+                               script.checkStack(2);
+                               script.push(long(i));
+                               tiles.pushField();
 
-                                       row.push_back(Tilemap::Index(index));
-                               }
+                               long index;
+                               top.get(index);
 
-                               indices[h] = row;
+                               row.push_back(Tilemap::Index(index));
                        }
-               }
-               else
-               {
-                       logError("invalid tiles in tilemap instruction");
-                       return 0;
+
+                       indices[h] = row;
                }
 
                Vector4 vertices[height+1][width+1];
@@ -315,16 +290,16 @@ struct Meh
                if (table.isTable())
                {
                        table.pushField("tile");
-                       if (top.isNumber()) top.get(index);
+                       top.get(index);
 
                        table.pushField("u_scale");
-                       if (top.isNumber()) top.get(width);
+                       top.get(width);
 
                        table.pushField("blend");
-                       if (top.isBoolean()) top.get(blending);
+                       top.get(blending);
 
                        table.pushField("fog");
-                       if (top.isBoolean()) top.get(fog);
+                       top.get(fog);
                }
 
                Vector4 vertices[2][width+1];
@@ -368,7 +343,7 @@ struct Meh
 };
 
 
-static void importScriptBindings(Script& script, Meh& scene)
+static void importSceneBindings(Script& script, Meh& scene)
 {
        script.importFunction("SetPlayfieldBounds",
                        boost::bind(&Meh::setPlayfieldBounds, &scene, _1));
@@ -388,6 +363,25 @@ static void importScriptBindings(Script& script, Meh& scene)
                        boost::bind(&Meh::makeTilemap, &scene, _1));
        script.importFunction("MakeBillboard",
                        boost::bind(&Meh::makeBillboard, &scene, _1));
+
+       long detail = 3;
+       Settings::getInstance().get("detail", detail);
+       script.push(detail);
+       script.set("detail");
+
+       script.push(Quad::LEFT);
+       script.set("LEFT");
+       script.push(Quad::RIGHT);
+       script.set("RIGHT");
+       script.push(Quad::TOP);
+       script.set("TOP");
+
+       script.push(Meh::X);
+       script.set("X");
+       script.push(Meh::Y);
+       script.set("Y");
+       script.push(Meh::Z);
+       script.set("Z");
 }
 
 
@@ -400,22 +394,14 @@ OctreeP loadScene(const std::string& name)
        Script script;
        script.importStandardLibraries();
        importLogScript(script);
-       importScriptBindings(script, cool);
-
-       long detail = 3;
-       Settings::getInstance().get("detail", detail);
-
-       script.push(detail);
-       script.set("detail");
+       importSceneBindings(script, cool);
 
-       logInfo("doing file...");
-       if (script.doFile(filePath) != 0)
+       if (script.doFile(filePath) != Script::SUCCESS)
        {
                std::string str;
                script[-1].get(str);
-               logError("lua error: %s", str.c_str());
+               logScript("%s", str.c_str());
        }
-       logInfo("done");
 
        cool.octree->sort();
        return cool.octree;
index 107e9938ca3131b18315e18c59894a5145f8f082..ce57bcd7d2a92332ba9a8ea54314b86d8c4b875a 100644 (file)
@@ -53,16 +53,21 @@ class Quad : public Entity
        
        Tilemap         tilemap_;
 
-       long            detail_;
        bool            blending_;
        bool            fog_;
 
 public:
 
+       enum SURFACE_TYPE
+       {
+               LEFT    = 1,
+               RIGHT   = 2,
+               TOP             = 3
+       };
+
        Quad(const Vector3 vertices[4], const std::string& texture,
                        Tilemap::Index tileIndex) :
                tilemap_(texture),
-               detail_(0),
                blending_(false),
                fog_(false)
        {
@@ -90,11 +95,6 @@ public:
                sphere_.radius = (aabb_.min - sphere_.point).length();
        }
 
-       void setDetail(long detail)
-       {
-               detail_ = detail;
-       }
-
        void setBlending(bool blending)
        {
                blending_ = blending;
index f954e583488a786e2740c7042a4ab89782697577..553e31a0717be1b242a5e0f8a2377212f4492157 100644 (file)
@@ -140,6 +140,73 @@ struct Script
                bool isData() const      { return (bool)lua_isuserdata(state, index); }
                bool isLightData() const { return (bool)lua_islightuserdata(state, index); }
 
+               /**
+                * Check the value and throw and error if its the wrong type.  This
+                * method never returns because it does a long jump.  Consequently,
+                * constructed C++ objects  which exist on the stack between the current
+                * frame and some lua function will not be destructed.  That's not a
+                * problem for objects that only exist on the stack, but any objects
+                * that allocate memory on the heap (such as containers or strings) will
+                * leak.  Therefore, you should only call this method after cleaning up
+                * such objects.
+                */
+
+               void requireType(TYPE type) const
+               {
+                       if (type != getType())
+                       {
+                               luaL_typerror(state, index, lua_typename(state, type));
+                       }
+               }
+
+               void throwError(const char* error)
+               {
+                       luaL_argerror(state, index, error);
+               }
+
+
+               Value& requireBoolean()
+               {
+                       if (!isBoolean()) luaL_typerror(state, index, "boolean");
+                       return *this;
+               }
+               Value& requireNumber()
+               {
+                       if (!isNumber()) luaL_typerror(state, index, "number");
+                       return *this;
+               }
+               Value& requireString()
+               {
+                       if (!isString()) luaL_typerror(state, index, "string");
+                       return *this;
+               }
+               Value& requireTable()
+               {
+                       if (!isTable()) luaL_typerror(state, index, "table");
+                       return *this;
+               }
+               Value& requireFunction()
+               {
+                       if (!isFunction()) luaL_typerror(state, index, "function");
+                       return *this;
+               }
+               Value& requireData()
+               {
+                       if (!isData()) luaL_typerror(state, index, "data");
+                       return *this;
+               }
+               Value& requireNil()
+               {
+                       if (!isNil()) luaL_typerror(state, index, "nil");
+                       return *this;
+               }
+               Value& requireThread()
+               {
+                       if (!isThread()) luaL_typerror(state, index, "thread");
+                       return *this;
+               }
+
+
                /**
                 * Get the type of the value.
                 */
@@ -155,7 +222,7 @@ struct Script
 
                std::string getTypeName() const
                {
-                       return std::string(lua_typename(state, (int)getType()));
+                       return std::string(luaL_typename(state, index));
                }
 
 
@@ -465,6 +532,22 @@ struct Script
        }
 
 
+       /**
+        * Throw an error with the value at the top of the stack.  This method never
+        * returns because it does a long jump.  Consequently, constructed C++
+        * objects  which exist on the stack between the current frame and some lua
+        * function will not be destructed.  That's not a problem for objects that
+        * only exist on the stack, but any objects that allocate memory on the heap
+        * (such as containers or strings) will leak.  Therefore, you should only
+        * call this method after cleaning up such objects.
+        */
+
+       void throwError()
+       {
+               lua_error(state_);
+       }
+
+
        /**
         * Get significant values.
         */
@@ -561,6 +644,10 @@ struct Script
        {
                lua_pushlstring(state_, value.c_str(), value.length());
        }
+       void push(const char* value)
+       {
+               lua_pushstring(state_, value);
+       }
        void push(const char* value, size_t length)
        {
                lua_pushlstring(state_, value, length);
index 53cb850f5a6f1cc661057ca4c6f10d4e5a31b3b2..5a321b01be9e53da843e43887d6def5029336a83 100644 (file)
@@ -78,7 +78,7 @@ void Settings::loadFromFiles(const std::vector<std::string>& filePaths)
                {
                        std::string str;
                        script_[-1].get(str);
-                       logWarning("running config file: %s", str.c_str());
+                       logScript("%s", str.c_str());
                        script_.clear();
                }
        }
This page took 0.082613 seconds and 4 git commands to generate.