AC_CANONICAL_TARGET
-AC_CONFIG_SRCDIR([src/YoinkApp.cc])
+AC_CONFIG_SRCDIR([src/GameLayer.cc])
AC_CONFIG_MACRO_DIR([m4])
AM_INIT_AUTOMAKE
[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.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cd "$current"
-#cscope -b -q
+cscope -b -q
-- 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,
-- 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,
-- Right side
ResetTransform()
- Rotate('y', 90)
+ Rotate(Y, 90)
Translate(7, 0, 0)
Scale(32)
MakeTilemap({
-- Top
ResetTransform()
- Rotate('x', 90)
+ Rotate(X, 90)
Translate(-2, 8, -6)
Scale(32)
MakeTilemap({
-- 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,
-- 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,
-- Pitched roof
ResetTransform()
-Rotate('x', 135)
+Rotate(X, 135)
Scale(1, 1.5, 1.5)
Translate(10, 5, 3)
Scale(32)
Scale(32)
MakeTilemap({
width = 3,
- surface_type = 'top',
+ surface_type = TOP,
tiles = {
-1, -1, -1
}
-- 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,
ResetTransform()
Scale(4, 1, 1)
- Rotate('y', -90)
+ Rotate(Y, -90)
Translate(1, -0.5, 1)
Scale(32)
MakeBillboard({
ResetTransform()
Scale(4, 1, 1)
- Rotate('y', -90)
+ Rotate(Y, -90)
Translate(9, -0.5, 1)
Scale(32)
MakeBillboard({
-- Left wall
ResetTransform()
- Rotate('y', -90)
+ Rotate(Y, -90)
Translate(19, 0, -3)
Scale(32)
MakeTilemap({
-- Right wall
ResetTransform()
- Rotate('y', -90)
+ Rotate(Y, -90)
Translate(23, 0, -3)
Scale(32)
MakeTilemap({
-- 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({
-- 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({
-- Finial
ResetTransform()
- Rotate('y', -90)
+ Rotate(Y, -90)
Translate(21, 6, -3)
Scale(32)
MakeTilemap({
-- 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,
-- 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,
-- Left grass
ResetTransform()
- Rotate('y', -90)
+ Rotate(Y, -90)
Translate(14, -0.5, 1)
Scale(32)
MakeTilemap({
-- Grass left of house
ResetTransform()
- Rotate('y', -90)
+ Rotate(Y, -90)
Translate(18, -0.5, 0)
Scale(32)
MakeBillboard({
-- Grass right of house
ResetTransform()
- Rotate('y', -90)
+ Rotate(Y, -90)
Translate(24, -0.5, 0)
Scale(32)
MakeBillboard({
ResetTransform()
Scale(2, 1, 1)
- Rotate('y', -90)
+ Rotate(Y, -90)
Translate(19, -0.5, 2)
Scale(32)
MakeBillboard({
ResetTransform()
Scale(2, 1, 1)
- Rotate('y', -90)
+ Rotate(Y, -90)
Translate(23, -0.5, 2)
Scale(32)
MakeBillboard({
-- 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,
ResetTransform()
Scale(2, 1, 1)
- Rotate('y', -90)
+ Rotate(Y, -90)
Translate(26, -0.5, 5)
Scale(32)
MakeBillboard({
ResetTransform()
Scale(2, 1, 1)
- Rotate('y', -90)
+ Rotate(Y, -90)
Translate(35, -0.5, 5)
Scale(32)
MakeBillboard({
-- Extra bit of back grass
ResetTransform()
- Rotate('y', -90)
+ Rotate(Y, -90)
Translate(34, -0.5, 0)
Scale(32)
MakeBillboard({
-- 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,
-- 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,
-- 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,
-- 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,
-- 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,
-- 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,
-- 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,
--- /dev/null
+
+/*******************************************************************************
+
+ Copyright (c) 2009, Charles McGarvey
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include <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: *************************************************/
+
*******************************************************************************/
-#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;
Mf::Camera camera;
Mf::OctreeP octree;
- Hud hud;
+ HudP hud;
};
-#endif // _YOINKAPP_HH_
+#endif // _GAMELAYER_HH_
/** vim: set ts=4 sw=4 tw=80: *************************************************/
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: *************************************************/
*/
#include <Moof/Drawable.hh>
+#include <Moof/Layer.hh>
#include <Moof/Math.hh>
#include <Moof/Rectangle.hh>
#include <Moof/Tilemap.hh>
};
-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
void resize(int width, int height);
void draw(Mf::Scalar alpha = 0.0) const;
+ bool handleEvent(Mf::Event& event);
private:
#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);
//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()
{
<< "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
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;
}
--- /dev/null
+
+/*******************************************************************************
+
+ Copyright (c) 2009, Charles McGarvey
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#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: *************************************************/
+
Moof/Hash.cc \
Moof/Hash.hh \
Moof/Interpolator.hh \
+ Moof/Layer.hh \
Moof/Log.cc \
Moof/Log.hh \
Moof/Math.hh \
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
*******************************************************************************/
+#include <algorithm>
#include <cstdlib> // exit
+#include <list>
#include <string>
#include <SDL/SDL.h>
#include "Dispatcher.hh"
#include "Engine.hh"
+#include "Event.hh"
#include "Log.hh"
#include "Random.hh"
#include "Settings.hh"
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)
{
* the exit code used to stop the loop.
*/
- int run()
+ void run()
{
Scalar ticksNow = Timer::getTicks();
fps = 0;
int frameAccum = 0;
- running = true;
do
{
Scalar newTicks = Timer::getTicks();
while (accumulator >= timestep)
{
dispatchEvents();
- interface->update(totalTime, timestep);
+ update(totalTime, timestep);
totalTime += timestep;
accumulator -= timestep;
}
}
- interface->draw(accumulator / timestep);
+ draw(accumulator / timestep);
video->swap();
nextDraw += drawRate;
Timer::sleep(std::min(std::min(nextStep, nextDraw),
Timer::getNextFire()), true);
}
- while (running);
-
- return exitCode;
+ while (!stack.empty());
}
-
void dispatchEvents()
{
SDL_Event event;
if (event.key.keysym.sym == SDLK_ESCAPE &&
(SDL_GetModState() & KMOD_CTRL) )
{
- exit(0);
+ // emergency escape
+ exit(0);
}
break;
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;
}
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
#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
{
};
private:
- Engine() {} // this class must be subclassed to be useful
-
class Impl;
boost::shared_ptr<Impl> impl_;
};
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);
}
--- /dev/null
+
+/*******************************************************************************
+
+ Copyright (c) 2009, Charles McGarvey
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#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: *************************************************/
+
va_end(args);
}
-static void logScript(const char* fmt, ...)
+void logScript(const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
void logDebug(const char* fmt, ...);
+void logScript(const char* fmt, ...);
class Script;
int logScript(Script& script);
void importLogScript(Script& script);
OctreeP octree;
+ enum AXIS
+ {
+ X = 0,
+ Y = 1,
+ Z = 2
+ };
+
Meh()
{
octree = Octree::alloc(Aabb());
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]);
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);
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;
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;
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];
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];
};
-static void importScriptBindings(Script& script, Meh& scene)
+static void importSceneBindings(Script& script, Meh& scene)
{
script.importFunction("SetPlayfieldBounds",
boost::bind(&Meh::setPlayfieldBounds, &scene, _1));
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");
}
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;
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)
{
sphere_.radius = (aabb_.min - sphere_.point).length();
}
- void setDetail(long detail)
- {
- detail_ = detail;
- }
-
void setBlending(bool blending)
{
blending_ = blending;
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.
*/
std::string getTypeName() const
{
- return std::string(lua_typename(state, (int)getType()));
+ return std::string(luaL_typename(state, index));
}
}
+ /**
+ * 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.
*/
{
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);
{
std::string str;
script_[-1].get(str);
- logWarning("running config file: %s", str.c_str());
+ logScript("%s", str.c_str());
script_.clear();
}
}