r6581 - in packages/branches/upstream: . pathogen pathogen/current pathogen/current/src
Barry deFreese
bddebian-guest at alioth.debian.org
Wed Apr 16 16:45:21 UTC 2008
Author: bddebian-guest
Date: 2008-04-16 16:45:21 +0000 (Wed, 16 Apr 2008)
New Revision: 6581
Added:
packages/branches/upstream/pathogen/
packages/branches/upstream/pathogen/current/
packages/branches/upstream/pathogen/current/Makefile
packages/branches/upstream/pathogen/current/src/
packages/branches/upstream/pathogen/current/src/BuildState.cpp
packages/branches/upstream/pathogen/current/src/GameApp.cpp
packages/branches/upstream/pathogen/current/src/sound.cpp
Log:
[svn-inject] Installing original source of pathogen
Added: packages/branches/upstream/pathogen/current/Makefile
===================================================================
--- packages/branches/upstream/pathogen/current/Makefile (rev 0)
+++ packages/branches/upstream/pathogen/current/Makefile 2008-04-16 16:45:21 UTC (rev 6581)
@@ -0,0 +1,22 @@
+# Pathogen Warrior
+#
+# Linux Makefile
+# Contributed by Ion
+#
+# $Id: Makefile,v 1.2 2004/07/12 16:05:50 tonic Exp $
+# $Revision: 1.2 $
+
+sources := $(wildcard *.cpp)
+objects := $(sources:%.cpp=%.o) errormsg.o
+
+all: pathogen
+
+CXXFLAGS := $(shell sdl-config --cflags)
+LDFLAGS := $(shell sdl-config --libs) -lSDL_image -lSDL_mixer -lGLU -lGL
+
+pathogen: $(objects)
+ $(CXX) $(LDFLAGS) -o $@ $^
+
+.PHONY: clean
+clean:
+ $(RM) pathogen $(objects)
Added: packages/branches/upstream/pathogen/current/src/BuildState.cpp
===================================================================
--- packages/branches/upstream/pathogen/current/src/BuildState.cpp (rev 0)
+++ packages/branches/upstream/pathogen/current/src/BuildState.cpp 2008-04-16 16:45:21 UTC (rev 6581)
@@ -0,0 +1,1003 @@
+/* Pathogen Warrior
+ * Copyright 2004 Jetro Lauha - http://iki.fi/jetro/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id: BuildState.cpp,v 1.14 2004/07/14 15:37:09 tonic Exp $
+ * $Revision: 1.14 $
+ */
+
+#include <assert.h>
+#include <math.h>
+#include "main.h"
+#include "SDL_image.h"
+
+
+enum QUADRIC_OBJ_ENUM
+{
+ SPHERE_SLICES = 20,
+ SPHERE_STACKS = 10,
+ CYLINDER_SLICES = 5,
+ CYLINDER_STACKS = 1
+};
+
+static GLUquadric *sQObj = NULL;
+static GLuint sSphereList = 0;
+static GLuint sCylinderLists = 0;
+
+
+static ProblemConfiguration sProblemConfigurations[] =
+{
+ //{ 3, { 4, 3 }, 0.04f },
+ { 2, { 1, 1 }, 0 },
+ { 2, { 2, 1 }, 0 },
+ { 3, { 1, 1 }, 0.01f },
+ { 2, { 3, 1 }, 0.01f },
+ { 2, { 4, 1 }, 0 },
+ { 3, { 2, 1 }, 0 },
+ { 3, { 3, 1 }, 0 },
+ { 3, { 3, 1 }, 0.01f },
+ { 2, { 5, 1 }, 0.01f },
+ { 3, { 2, 2 }, 0 },
+ { 3, { 2, 2 }, 0.01f },
+ { 2, { 6, 1 }, 0.02f },
+ { 3, { 3, 2 }, 0 },
+ { 3, { 2, 3 }, 0 },
+ { 3, { 2, 3 }, 0.01f },
+ { 3, { 1, 4 }, 0 },
+ { 3, { 3, 3 }, 0 },
+ { 3, { 4, 1 }, 0 },
+ { 3, { 4, 2 }, 0 },
+ { 3, { 3, 3 }, 0.01f },
+ { 3, { 4, 1 }, 0.01f },
+ { 3, { 4, 2 }, 0.01f },
+ { 3, { 4, 3 }, 0.01f },
+ { 3, { 3, 3 }, 0.02f },
+ { 3, { 4, 1 }, 0.02f },
+ { 3, { 4, 2 }, 0.02f },
+ { 3, { 4, 3 }, 0.02f },
+ { 3, { 3, 3 }, 0.04f },
+ { 3, { 4, 1 }, 0.04f },
+ { 3, { 4, 2 }, 0.04f },
+ { 3, { 4, 3 }, 0.04f },
+ { 3, { 3, 3 }, 0.06f },
+ { 3, { 4, 1 }, 0.06f },
+ { 3, { 4, 2 }, 0.06f },
+ { 3, { 4, 3 }, 0.06f },
+};
+#define SPROBLEMCONFIGURATIONS_COUNT (sizeof(sProblemConfigurations) / sizeof(sProblemConfigurations[0]))
+static INT sCurrentProblemConfiguration = -1;
+
+
+static FLOAT getLevelTranslation(INT level)
+{
+ return (MAX_PROBLEM_STRUCTURE_LEVELS + 1 - level) * 0.1f;
+}
+
+
+static FLOAT smoothStep(FLOAT x, FLOAT a, FLOAT b)
+{
+ if (x < a)
+ return 0.f;
+ if (x >= b)
+ return 1.f;
+ x = (x - a) / (b - a); // normalize to [0..1]
+ return x * x * (3 - 2 * x);
+}
+
+static FLOAT smoothPulse(FLOAT a1, FLOAT a2, FLOAT b1, FLOAT b2, FLOAT x)
+{
+ return smoothStep(x, a1, a2) - smoothStep(x, b1, b2);
+}
+
+
+BuildState::BuildState() :
+ mScore(0), mPathogenCount(0),
+ mProblemRoot(MHT_BALL),
+ mMouseX(0), mMouseY(0),
+ mHighlight(FALSE), mDragging(FALSE),
+ mMapMask(NULL)
+{
+ mFPS = 60;
+
+ sQObj = gluNewQuadric();
+ assert(sQObj != NULL);
+ gluQuadricNormals(sQObj, GLU_FLAT);
+ gluQuadricTexture(sQObj, GL_FALSE);
+
+ sSphereList = glGenLists(1);
+ glNewList(sSphereList, GL_COMPILE);
+ gluSphere(sQObj, 0.1, SPHERE_SLICES, SPHERE_STACKS);
+ glEndList();
+
+ gluQuadricNormals(sQObj, GLU_NONE);
+ sCylinderLists = glGenLists(MAX_PROBLEM_STRUCTURE_LEVELS);
+ INT a;
+ for (a = 0; a < MAX_PROBLEM_STRUCTURE_LEVELS; ++a)
+ {
+ const GLdouble radius = 0.02;
+ glNewList(sCylinderLists + a, GL_COMPILE);
+ gluCylinder(sQObj, radius, radius, getLevelTranslation(a),
+ CYLINDER_SLICES, CYLINDER_STACKS);
+ glEndList();
+ }
+}
+
+
+BuildState::~BuildState()
+{
+ gluDeleteQuadric(sQObj);
+ sQObj = NULL;
+
+ glDeleteLists(sSphereList, 1);
+}
+
+
+BOOL BuildState::init()
+{
+ mHexImage = loadImage("data/hex.png");
+ mBallImage = loadImage("data/ball.png");
+ mShineImage = loadImage("data/shine.png");
+ mLinkImages[0] = loadImage("data/link1.png");
+ mLinkImages[1] = loadImage("data/link2.png");
+ mLinkImages[2] = loadImage("data/link3.png");
+ mMapImage = loadImage("data/map.png");
+ mCircleImage = loadImage("data/circle.png");
+ mBlockImage = loadImage("data/block.png");
+ mSquareImage = loadImage("data/square.png");
+ mMapMask = IMG_Load("data/mapmask.png");
+
+ return TRUE;
+}
+
+
+void BuildState::deinit()
+{
+ freeImage(mHexImage);
+ freeImage(mBallImage);
+ freeImage(mShineImage);
+ freeImage(mLinkImages[0]);
+ freeImage(mLinkImages[1]);
+ freeImage(mLinkImages[2]);
+ freeImage(mMapImage);
+ freeImage(mCircleImage);
+ freeImage(mBlockImage);
+ freeImage(mSquareImage);
+ SDL_FreeSurface(mMapMask);
+}
+
+
+BOOL BuildState::update(UINT32 time, App::KeyEventList &keyEvents)
+{
+ mTime = time;
+
+ mScrollX = (mScrollX * 9 + mScrollXDest) * 0.1f;
+ mScrollY = (mScrollY * 9 + mScrollYDest) * 0.1f;
+
+ // all key presses are handled in onKey* event methods
+ keyEvents.clear();
+
+ if (mNormalizedProblemTime > 1 && !mMutationTriggerNewProblem && !mGameOver)
+ {
+ mGameOverTime = mTime;
+ mGameOver = TRUE;
+ TextRow tr("Game Over!", mTime, 4000);
+ mInfoText.push_back(tr);
+ char text[256];
+ sprintf(text, "Pathogen %u defeated you.", mPathogenCount);
+ tr.str = text;
+ tr.age = 4500;
+ mInfoText.push_back(tr);
+ }
+
+ if (!mGameOver && verifyProblem() && !mMutationTriggerNewProblem)
+ {
+ //createProblem();
+ INT32 points = (mProblemStartTime + mProblemTime - mTime) / 10;
+ if (points > 0)
+ mScore += points;
+ mutateProblem();
+ mMutationTriggerNewProblem = TRUE;
+ }
+
+ if (mMutationTriggerTime > 0)
+ {
+ if (mTime - mMutationTriggerTime >= 1000 &&
+ !mMutationTriggerMutated)
+ {
+ if (mMutationTriggerNewProblem)
+ createProblem();
+ else
+ mutateNodes(&mProblemRoot);
+ mMutationTriggerMutated = TRUE;
+ }
+ if (mTime - mMutationTriggerTime >= 2000)
+ mMutationTriggerTime = 0;
+ }
+
+ mNormalizedProblemTime = (FLOAT)(mTime - mProblemStartTime) / mProblemTime;
+
+ TextList::iterator it = mInfoText.begin();
+ for (; it != mInfoText.end(); ++it)
+ {
+ TextRow &row = *it;
+ if (row.startTime + row.age < mTime)
+ {
+ mInfoText.erase(it);
+ break;
+ }
+ }
+
+ return TRUE;
+}
+
+
+void BuildState::onActivate(UINT32 tick)
+{
+ mTime = tick;
+
+ mScore = 0;
+ mPathogenCount = 0;
+ sCurrentProblemConfiguration = -1;
+ mGameOverTime = 0;
+ mGameOver = FALSE;
+
+ createProblem();
+}
+
+
+void BuildState::onDeactivate()
+{
+}
+
+
+void BuildState::onKeyDown(const SDLKey &key)
+{
+ switch (key)
+ {
+ /*
+ case SDLK_RETURN:
+ //createProblem();
+ mutateProblem();
+ mMutationTriggerNewProblem = TRUE;
+ break;
+ */
+ case SDLK_SPACE:
+ if (mGameOver)
+ App::getInstance()->setState(GS_TITLE);
+ else
+ mutateProblem();
+ break;
+ case SDLK_DOWN: case SDLK_KP2:
+ mScrollYDest -= 1;
+ break;
+ case SDLK_UP: case SDLK_KP8:
+ mScrollYDest += 1;
+ break;
+ case SDLK_LEFT: case SDLK_KP4:
+ mScrollXDest += 1;
+ break;
+ case SDLK_RIGHT: case SDLK_KP6:
+ mScrollXDest -= 1;
+ break;
+ }
+}
+
+
+void BuildState::onKeyUp(const SDLKey &key)
+{
+}
+
+
+void BuildState::onMouseDown(const SDL_MouseButtonEvent &event)
+{
+ if (event.button == SDL_BUTTON_LEFT)
+ {
+ if (mHighLightMapCircle)
+ mutateProblem();
+ else
+ {
+ // highlight node
+ mHighlight = TRUE;
+ mMouseDownNode = mHighlightNode;
+ // start fiddling with the hexagon map
+ mDragStartNode = mHighlightNode;
+ mDragging = TRUE;
+ }
+ }
+}
+
+
+void BuildState::onMouseUp(const SDL_MouseButtonEvent &event)
+{
+ if (event.button == SDL_BUTTON_LEFT && mHighlight)
+ {
+ if (mHighlight)
+ {
+ if (mDragging && mDragStartNode != mHighlightNode)
+ {
+ HexagonMap::iterator it;
+ MapNode *n1 = NULL, *n2 = NULL;
+ it = mMap.find(mDragStartNode);
+ if (it != mMap.end())
+ {
+ n1 = (*it).second;
+ mMap.erase(it);
+ }
+ it = mMap.find(mHighlightNode);
+ if (it != mMap.end())
+ {
+ n2 = (*it).second;
+ mMap.erase(it);
+ }
+ if (n1 != NULL)
+ {
+ mMap[mHighlightNode] = n1;
+ n1->position = mHighlightNode;
+ }
+ if (n2 != NULL)
+ {
+ mMap[mDragStartNode] = n2;
+ n2->position = mDragStartNode;
+ }
+ }
+ mDragging = FALSE;
+ mHighlight = FALSE;
+ }
+ if (mDragStartNode == mHighlightNode)
+ {
+ HexagonMap::iterator it = mMap.find(mHighlightNode);
+ if (it == mMap.end())
+ {
+ // current node is empty - make a new link there
+ LinkNode *node = new LinkNode(MHT_LINK);
+ mMap[mHighlightNode] = node;
+ }
+ else
+ {
+ MapNode *node = (*it).second;
+ // if current node is a link, rotate or erase it
+ if (mHighlightNode == mMouseDownNode &&
+ node->type == MHT_LINK &&
+ ++((LinkNode *)node)->link >= 3)
+ {
+ delete node;
+ mMap.erase(it);
+ }
+ }
+ }
+ }
+}
+
+
+void BuildState::onMouseMotion(const SDL_MouseMotionEvent &event)
+{
+ mMouseX = event.x;
+ mMouseY = event.y;
+
+ if ((event.state & SDL_BUTTON(1)) && !(event.state & SDL_BUTTON(3)))
+ {
+ /*
+ // drag with left button
+ if (mDragStartNode != mHighlightNode)
+ {
+ HexagonMap::iterator it;
+ MapNode *n1 = NULL, *n2 = NULL;
+ it = mMap.find(mDragStartNode);
+ if (it != mMap.end())
+ {
+ n1 = (*it).second;
+ mMap.erase(it);
+ }
+ it = mMap.find(mHighlightNode);
+ if (it != mMap.end())
+ {
+ n2 = (*it).second;
+ mMap.erase(it);
+ }
+ if (n1 != NULL)
+ {
+ mMap[mHighlightNode] = n1;
+ n1->position = mHighlightNode;
+ }
+ if (n2 != NULL)
+ {
+ mMap[mDragStartNode] = n2;
+ n2->position = mDragStartNode;
+ }
+
+ mDragStartNode = mHighlightNode;
+ }
+ */
+ }
+ else if (!(event.state & SDL_BUTTON(1)) && (event.state & SDL_BUTTON(3)))
+ {
+ // drag with right button
+ mScrollXDest -= event.xrel / ((FLOAT)mHexImage.w * 2 / 3);
+ mScrollYDest -= event.yrel / (FLOAT)mHexImage.h;
+ }
+}
+
+
+void BuildState::createProblem()
+{
+ clearProblem();
+
+ ++sCurrentProblemConfiguration;
+ if (sCurrentProblemConfiguration >= SPROBLEMCONFIGURATIONS_COUNT)
+ sCurrentProblemConfiguration = SPROBLEMCONFIGURATIONS_COUNT - 1;
+
+ INT balls = buildNodes(&mProblemRoot, NULL, 0,
+ sProblemConfigurations[sCurrentProblemConfiguration].levels);
+ mutateNodes(&mProblemRoot);
+
+ mProblemTime = balls * TIME_PER_COMPOUND;
+ mProblemStartTime = mTime;
+ mNormalizedProblemTime = 0;
+
+ ++mPathogenCount;
+
+ char text[256];
+ TextRow tr("", mTime, 3000);
+ sprintf(text, "Pathogen %u", mPathogenCount);
+ tr.str = text;
+ mInfoText.push_back(tr);
+ sprintf(text, "%d compounds", balls);
+ tr.str = text;
+ mInfoText.push_back(tr);
+ sprintf(text, "Time: %d seconds", mProblemTime / 1000);
+ tr.str = text;
+ mInfoText.push_back(tr);
+
+
+ mMutationTriggerNewProblem = FALSE;
+
+ // find a position from the map image
+
+ int lockResult = SDL_LockSurface(mMapMask);
+ if (lockResult < 0)
+ return;
+ assert(mMapMask->format->BitsPerPixel == 32);
+
+ BOOL found = FALSE;
+ do {
+ INT x = rand() % mMapMask->w;
+ INT y = rand() % mMapMask->h;
+ UINT32 pix = *((UINT32 *)((UINT8 *)mMapMask->pixels + y * mMapMask->pitch) + x);
+ INT r = (pix >> 16) & 0xff;
+ INT g = (pix >> 8) & 0xff;
+ INT b = pix & 0xff;
+ if (r > 128 && g > 128 && b > 128)
+ {
+ found = TRUE;
+ mMapImagePosition.x = x;
+ mMapImagePosition.y = y;
+ }
+ } while(!found);
+
+ SDL_UnlockSurface(mMapMask);
+}
+
+
+BOOL BuildState::verifyProblem()
+{
+ return verifyNode(&mProblemRoot) == mProblemRoot.children.size();
+}
+
+
+void BuildState::mutateProblem()
+{
+ if (mMutationTriggerTime > 0)
+ return;
+ mMutationTriggerTime = mTime;
+ mMutationTriggerMutated = FALSE;
+}
+
+
+INT BuildState::verifyNode(BallNode *node)
+{
+ if (node->children.size() == 0)
+ return 0;
+
+ const INT dirX[6] = { -1, -1, 0, 0, 1, 1 };
+ const INT dirY[2][6] = { { -1, 0, -1, 1, -1, 0 }, { 0, 1, -1, 1, 0, 1 } };
+ const INT dirLink[6] = { 2, 1, 0, 0, 1, 2 };
+ UINT dir;
+ INT x = node->position.x;
+ INT y = node->position.y;
+ INT childrenFound = 0;
+
+ //INT gx = mProblemRoot.position.x + dirX[aa];
+ //INT gy = mProblemRoot.position.y + dirY[xi][aa];
+
+ for (dir = 0; dir < 6; ++dir)
+ {
+ UINT xi = node->position.x & 1;
+ Position p(x + dirX[dir], y + dirY[xi][dir]);
+ HexagonMap::iterator it = mMap.find(p);
+ if (it == mMap.end())
+ continue;
+
+ MapNode *testNode = (*it).second;
+ if (testNode->type != MHT_LINK)
+ continue;
+ LinkNode *linkNode = (LinkNode *)testNode;
+ while (it != mMap.end() && testNode->type == MHT_LINK &&
+ linkNode->link == dirLink[dir])
+ {
+ xi = 1 - xi;
+ p.x += dirX[dir];
+ p.y += dirY[xi][dir];
+ it = mMap.find(p);
+ if (it != mMap.end())
+ {
+ testNode = (*it).second;
+ if (testNode->type == MHT_LINK)
+ linkNode = (LinkNode *)testNode;
+ }
+ }
+ /*
+ //BallNode::BallNodeSet parentChildren = node->parent->children;
+ if (it == mMap.end() || testNode.type != MHT_BALL ||
+ //parentChildren.find((BallNode *)&testNode) == parentChildren.end())
+ node->children.find((BallNode *)&testNode) == node->children.end())
+ return childrenFound;
+ else
+ {
+ if (verifyNode((BallNode *)&testNode) == node->children.size())
+ ++childrenFound;
+ }
+ */
+ if (it != mMap.end() && testNode->type == MHT_BALL)
+ {
+ BallNode *ballNode = (BallNode *)testNode;
+ BOOL foundChild = node->children.find(ballNode) != node->children.end();
+ if (foundChild)
+ {
+ INT children = verifyNode(ballNode);
+ if (children == ballNode->children.size())
+ ++childrenFound;
+ }
+ }
+ }
+
+ return childrenFound;
+}
+
+
+INT BuildState::buildNodes(BallNode *node, BallNode *parent, INT level, INT depth)
+{
+ INT balls = 1;
+
+ node->parent = parent;
+ /*
+ node->color.red = (float)rand() / RAND_MAX;
+ node->color.green = (float)rand() / RAND_MAX;
+ node->color.blue = (float)rand() / RAND_MAX;
+ */
+ FLOAT r, g, b;
+ FLOAT h, l, s;
+ BOOL added = FALSE;
+ //FLOAT threshold = 0.15f;
+ FLOAT threshold = 0.05f;
+ UINT32 tries = 0;
+ do {
+ h = 360 * ((float)rand() / RAND_MAX);
+ l = ((float)rand() / RAND_MAX) * 0.7f + 0.3f;
+ s = ((float)rand() / RAND_MAX) * 0.6f + 0.4f;
+
+ hls2rgb(&r, &g, &b, h, l, s);
+
+ FLOAT minDistSq = 1000000;
+ int a;
+ for (a = 0; a < mColors.size(); ++a)
+ {
+ FLOAT rd = mColors[a].red - r;
+ FLOAT gd = mColors[a].green - g;
+ FLOAT bd = mColors[a].blue - b;
+ rd *= 0.3f;
+ gd *= 0.59f;
+ bd *= 0.11f;
+ FLOAT distSq = rd * rd + gd * gd + bd * bd;
+ if (distSq < minDistSq)
+ minDistSq = distSq;
+ }
+
+ if (minDistSq > threshold)
+ {
+ Color c(r, g, b);
+ mColors.push_back(c);
+
+ node->mapColor.red = r;
+ node->mapColor.green = g;
+ node->mapColor.blue = b;
+ hls2rgb(&r, &g, &b, h, l * 0.9f, s); // make 3D ball a bit darker
+ node->color.red = r;
+ node->color.green = g;
+ node->color.blue = b;
+ added = TRUE;
+ }
+ if (++tries > 1000)
+ {
+ // fallback just to be safe..
+ tries = 0;
+ threshold -= 0.01f;
+ }
+ } while (!added);
+
+ if (parent == NULL)
+ {
+ node->position.x = 0;
+ node->position.y = 0;
+ mMap[node->position] = node;
+ }
+ else
+ {
+ Position p;
+ p.x = parent->position.x;
+ p.y = parent->position.y;
+ BOOL foundPos = FALSE;
+ do {
+ if (mMap.find(p) == mMap.end())
+ foundPos = TRUE;
+ else
+ {
+ p.x += rand() % 3 - 1;
+ p.y += rand() % 3 - 1;
+ }
+ } while (!foundPos);
+ assert(mMap.find(p) == mMap.end());
+ node->position = p;
+ mMap[p] = node;
+ }
+
+
+ /*
+ --depth;
+ assert(depth >= 0);
+ if (depth <= 0)
+ return balls;
+ */
+ ++level;
+ assert(level <= depth);
+ if (level >= depth)
+ return balls;
+
+ const INT newNodeCount = sProblemConfigurations[sCurrentProblemConfiguration].branches[level - 1];
+ INT a;
+ for (a = 0; a < newNodeCount; ++a)
+ {
+ BallNode *newNode = new BallNode(MHT_BALL);
+ node->children.insert(newNode);
+ balls += buildNodes(newNode, node, level, depth);
+ }
+
+ return balls;
+}
+
+
+void BuildState::mutateNodes(BallNode *node)
+{
+ node->direction.angle = 360 * (float)rand() / RAND_MAX;
+ node->direction.x = 2 * (float)rand() / RAND_MAX - 1;
+ node->direction.y = 2 * (float)rand() / RAND_MAX - 1;
+ node->direction.z = 2 * (float)rand() / RAND_MAX - 1;
+
+ BallNode::BallNodeSet::iterator it = node->children.begin();
+ BallNode::BallNodeSet::iterator itend = node->children.end();
+
+ for (; it != itend; ++it)
+ mutateNodes(*it);
+}
+
+
+void BuildState::clearProblem()
+{
+ mScrollX = mScrollXDest = 1;
+ mScrollY = mScrollYDest = 1;
+
+ mColors.clear();
+ clearNode(&mProblemRoot);
+ mMap.clear();
+}
+
+
+void BuildState::clearNode(BallNode *node)
+{
+ BallNode::BallNodeSet::iterator it = node->children.begin();
+ BallNode::BallNodeSet::iterator itend = node->children.end();
+
+ for (; it != itend; ++it)
+ {
+ clearNode(*it);
+ delete *it;
+ }
+ node->children.clear();
+}
+
+
+void BuildState::render(SDL_Surface * /*screen*/)
+{
+ FLOAT r = 0;
+ if (mGameOver)
+ r += 0.3f * smoothStep(mTime, mGameOverTime, mGameOverTime + 2000);
+ clear(0.3f + r, 0.3f, 0.4f);
+
+ renderModel();
+ render2D();
+}
+
+
+void BuildState::render2D()
+{
+ glDisable(GL_LIGHTING);
+ enter2DMode(WIDTH, HEIGHT);
+
+ // draw map image and the pulsating circle
+ INT mapX = WIDTH - mMapImage.w;
+ INT mapY = (HEIGHT / 3 - mMapImage.h) / 3;
+ drawImage(mMapImage, mapX, mapY);
+ FLOAT scale = 0.02f + sin(mTime * 0.004f) * 0.02f + 1.5f * mNormalizedProblemTime;
+ FLOAT radius = scale * mCircleImage.w / 2;
+ INT circlePosX = mapX + mMapImagePosition.x;
+ INT circlePosY = mapY + mMapImagePosition.y;
+ BOOL inside = (mMouseX - circlePosX) * (mMouseX - circlePosX) +
+ (mMouseY - circlePosY) * (mMouseY - circlePosY) <
+ radius * radius;
+ mHighLightMapCircle = inside;
+ drawImageRotatedCenteredScaledAdditive(mCircleImage,
+ circlePosX, circlePosY,
+ 0, scale, 1, inside ? 0.5f : 0, 0);
+
+ // draw time bar below the map
+ FLOAT timeBarWidth = (1 - mNormalizedProblemTime) * mMapImage.w;
+ if (timeBarWidth < 1) timeBarWidth = 1;
+ if (timeBarWidth > mMapImage.w) timeBarWidth = mMapImage.w;
+ drawImageScaled(mBlockImage,
+ WIDTH - timeBarWidth, mapY + mMapImage.h + 8,
+ timeBarWidth, mBlockImage.h);
+
+ renderHexagonMap();
+
+ // draw text rows
+ GameApp *app = (GameApp *)App::getInstance();
+ Font *font = app->getFont();
+ INT y = HEIGHT / 2 - mInfoText.size() * font->getFontHeight() / 2;
+ TextList::iterator it = mInfoText.begin();
+ for (; it != mInfoText.end(); ++it)
+ {
+ TextRow &row = *it;
+ const char *text = row.str.c_str();
+ FLOAT alpha = 1 - smoothStep(mTime,
+ row.startTime + row.age * 0.9f,
+ row.startTime + row.age);
+ font->drawString(WIDTH / 3, y,
+ FONT_ALIGN_HORIZ_CENTER, text,
+ row.color.red, row.color.green, row.color.blue,
+ alpha);
+ y += font->getFontHeight();
+ }
+
+ // score
+ char scoreStr[32];
+ sprintf(scoreStr, "Score: %u", mScore);
+ font->drawString(WIDTH - mMapImage.w, HEIGHT / 3,
+ FONT_ALIGN_VERT_CENTER, scoreStr);
+
+ // mutation changing
+ if (mMutationTriggerTime > 0)
+ {
+ FLOAT alpha = smoothPulse(0, 1000, 1000, 2000, mTime - mMutationTriggerTime);
+ font->drawString(WIDTH - 1, HEIGHT / 3 + font->getFontHeight() * 4,
+ FONT_ALIGN_RIGHT | FONT_ALIGN_VERT_CENTER,
+ "Fetching a pathogen sample...", 0.5f, 0.75f, 1, alpha);
+ }
+
+ // game over anim
+ if (mGameOver && mTime > mGameOverTime + 5000)
+ {
+ UINT32 startTime = mGameOverTime + 5000;
+ FLOAT angle = mTime * 0.001f;
+ FLOAT scale = (mTime - startTime) * 0.01f;
+ drawImageRotatedCenteredScaled(mSquareImage, WIDTH / 2, HEIGHT / 2,
+ angle, scale);
+ if (scale > 35)
+ App::getInstance()->setState(GS_TITLE);
+ }
+
+ leave2DMode();
+}
+
+
+void BuildState::renderNode(BallNode *node, INT level)
+{
+ glRotatef(mTime * sProblemConfigurations[sCurrentProblemConfiguration].rotation, 1, 1, 1);
+
+ glColor3f(node->color.red, node->color.green, node->color.blue);
+ glCallList(sSphereList);
+
+ BallNode::BallNodeSet::iterator it = node->children.begin();
+ BallNode::BallNodeSet::iterator itend = node->children.end();
+
+ for (; it != itend; ++it)
+ {
+ glPushMatrix();
+
+ BallNode *node = *it;
+
+ glRotatef(node->direction.angle,
+ node->direction.x,
+ node->direction.y,
+ node->direction.z);
+ FLOAT translation = getLevelTranslation(level);
+ glDisable(GL_LIGHTING);
+ glColor3f(0, 0, 0);
+ glCallList(sCylinderLists + level);
+ glEnable(GL_LIGHTING);
+ glTranslatef(0, 0, translation);
+
+ renderNode(node, level + 1);
+
+ glPopMatrix();
+ }
+}
+
+
+void BuildState::renderModel()
+{
+ const INT viewportWidth = WIDTH / 2;
+ const INT viewportHeight = HEIGHT * 2 / 3;
+ glViewport(WIDTH / 2, 0, viewportWidth, viewportHeight);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ gluPerspective(45, (float)viewportWidth / viewportHeight, 0.01f, 5);
+ glMatrixMode(GL_MODELVIEW);
+
+ glLoadIdentity();
+
+ glEnable(GL_DEPTH_TEST);
+
+ glEnable(GL_LIGHTING);
+ glEnable(GL_LIGHT0);
+ glEnable(GL_CULL_FACE);
+ glCullFace(GL_BACK);
+ glShadeModel(GL_FLAT);
+
+ GLfloat lightPosition[] = { 0, 2, 2, 0 };
+ glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
+ GLfloat lightAmbient[] = { 0.2f, 0.0f, 0.0f, 1 };
+ glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmbient);
+ GLfloat lightDiffuse[] = { 1, 1, 1, 1 };
+ glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiffuse);
+ GLfloat lightSpecular[] = { 1, 1, 1, 1 };
+ glLightfv(GL_LIGHT0, GL_SPECULAR, lightSpecular);
+
+ GLfloat zeros[] = { 0, 0, 0, 1 };
+ GLfloat ones[] = { 1, 1, 1, 1 };
+ glMaterialfv(GL_FRONT, GL_AMBIENT, zeros);
+ glMaterialfv(GL_FRONT, GL_DIFFUSE, ones);
+ glMaterialfv(GL_FRONT, GL_SPECULAR, ones);
+ glMaterialfv(GL_FRONT, GL_EMISSION, zeros);
+ glMaterialf(GL_FRONT, GL_SHININESS, 60);
+
+ glColorMaterial(GL_FRONT, GL_DIFFUSE);
+ glEnable(GL_COLOR_MATERIAL);
+
+ FLOAT yOffset = -0.1f;
+ if (mMutationTriggerTime > 0)
+ yOffset -= 2 * smoothPulse(0, 1000, 1000, 2000, mTime - mMutationTriggerTime);
+ glTranslatef(0, yOffset, -2);
+
+ glRotatef(mTime * 0.05f, 0, 1, 0);
+
+ BallNode *node = &mProblemRoot;
+ renderNode(node, 0);
+}
+
+
+void BuildState::renderHexagonMap()
+{
+ Position p;
+ FLOAT columnWidth = mHexImage.w * 2 / 3;
+ FLOAT cellWidth = mHexImage.w;
+ FLOAT cellHeight = mHexImage.h;
+ INT gx, gy;
+ INT mapCenterX = (INT)mScrollX;
+ INT mapCenterY = (INT)mScrollY;
+ Position mouseNode;
+ FLOAT mouseDistSq = 10000000000.f;
+
+ for (gy = -8; gy < 5; ++gy)
+ {
+ for (gx = -6 + mapCenterX % 2; gx < 6; ++gx)
+ {
+ p.x = gx + mapCenterX;
+ p.y = gy + mapCenterY;
+ FLOAT x = (gx + 1 - fmod(mScrollX, 1)) * columnWidth;
+ FLOAT y = (gy + 1 - fmod(mScrollY, 1)) * cellHeight;
+ x += WIDTH / 4;
+ y += HEIGHT / 2 + (p.x & 1) * cellHeight / 2;
+ const FLOAT fadeStartX = WIDTH / 2 - columnWidth;
+ const FLOAT fadeEndX = WIDTH / 2 + columnWidth * 2;
+ FLOAT alpha = 1 - smoothStep(x, fadeStartX, fadeEndX);
+
+ FLOAT centerX = x + cellWidth / 2;
+ FLOAT centerY = y + cellHeight / 2;
+ FLOAT distSq = (centerX - mMouseX) * (centerX - mMouseX) +
+ (centerY - mMouseY) * (centerY - mMouseY);
+ if (distSq < mouseDistSq)
+ {
+ mouseNode = p;
+ mouseDistSq = distSq;
+ }
+
+ drawImage(mHexImage, x, y, 1, 1, 1, alpha);
+ if (mHighlight && mHighlightNode.x == p.x && mHighlightNode.y == p.y)
+ drawImageAdditive(mHexImage, x, y, 0, 1, 1, 1, alpha);
+ if (mDragging && mDragStartNode.x == p.x && mDragStartNode.y == p.y)
+ {
+ FLOAT pulse = (FLOAT)(sin(mTime * 0.02f) * 0.5f + 0.5f);
+ drawImageAdditive(mHexImage, x, y, 0, 1, 1, 1, alpha * pulse);
+ }
+ /*
+ if (p.x == 0 && p.y == 0)
+ drawImageAdditive(mHexImage, x, y, 0, 1, 1, 1, alpha);
+ */
+ /*
+ const INT dirX[6] = { -1, -1, 0, 0, 1, 1 };
+ const INT dirY[2][6] = { { -1, 0, -1, 1, -1, 0 }, { 0, 1, -1, 1, 0, 1 } };
+ int aa;
+ for (aa = 0; aa < 6; ++aa) {
+ UINT xi = mProblemRoot.position.x & 1;
+ INT gx = mProblemRoot.position.x + dirX[aa];
+ INT gy = mProblemRoot.position.y + dirY[xi][aa];
+ if (p.x == gx && p.y == gy)
+ drawImageAdditive(mHexImage, x, y, 0, 1, 1, 1, alpha);
+ }
+ */
+
+
+ HexagonMap::iterator it = mMap.find(p);
+ if (it != mMap.end())
+ {
+ MapNode &node = *(*it).second;
+ switch (node.type)
+ {
+ case MHT_BALL:
+ {
+ x += columnWidth / 4;
+ BallNode &bn = (BallNode &)node;
+ drawImage(mBallImage, x, y,
+ bn.mapColor.red,
+ bn.mapColor.green,
+ bn.mapColor.blue, alpha);
+ drawImageAdditive(mShineImage, x, y, 0, 1, 1, 1, alpha);
+ }
+ break;
+ case MHT_LINK:
+ {
+ LinkNode &ln = (LinkNode &)node;
+ assert(ln.link < 3);
+ drawImage(mLinkImages[ln.link], x, y, 1, 1, 1, alpha);
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ mHighlightNode = mouseNode;
+}
Added: packages/branches/upstream/pathogen/current/src/GameApp.cpp
===================================================================
--- packages/branches/upstream/pathogen/current/src/GameApp.cpp (rev 0)
+++ packages/branches/upstream/pathogen/current/src/GameApp.cpp 2008-04-16 16:45:21 UTC (rev 6581)
@@ -0,0 +1,81 @@
+/* Pathogen Warrior
+ * Copyright 2004 Jetro Lauha - http://iki.fi/jetro/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id: GameApp.cpp,v 1.9 2004/07/14 15:37:09 tonic Exp $
+ * $Revision: 1.9 $
+ */
+
+#include "main.h"
+
+
+GameApp::GameApp() :
+ mBuildState(NULL), mTitleState(NULL), mFont(NULL)
+{
+}
+
+
+GameApp::~GameApp()
+{
+ if (mBuildState != NULL)
+ mBuildState->deinit();
+ delete mBuildState;
+ if (mTitleState != NULL)
+ mTitleState->deinit();
+ delete mTitleState;
+}
+
+
+BOOL GameApp::init()
+{
+ BOOL result = App::init();
+
+ if (!result)
+ return result;
+
+ mFont = new Font("data/font.png");
+
+ mBuildState = new BuildState;
+ mBuildState->init();
+
+ mTitleState = new TitleState;
+ mTitleState->init();
+
+ if (mBuildState == NULL || mTitleState == NULL)
+ return FALSE;
+ setState(GS_TITLE);
+
+ return TRUE;
+}
+
+
+char * GameApp::getCaption()
+{
+ return CAPTION_STR;
+}
+
+
+State * GameApp::getStateHandler(INT state)
+{
+ switch (state)
+ {
+ case GS_TITLE:
+ return mTitleState;
+ case GS_BUILD:
+ return mBuildState;
+ }
+ return NULL;
+}
Added: packages/branches/upstream/pathogen/current/src/sound.cpp
===================================================================
--- packages/branches/upstream/pathogen/current/src/sound.cpp (rev 0)
+++ packages/branches/upstream/pathogen/current/src/sound.cpp 2008-04-16 16:45:21 UTC (rev 6581)
@@ -0,0 +1,131 @@
+/* Pathogen Warrior
+ * Copyright 2004 Jetro Lauha - http://iki.fi/jetro/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id: sound.cpp,v 1.4 2004/07/14 15:37:03 tonic Exp $
+ * $Revision: 1.4 $
+ */
+
+#include "main.h"
+#include "SDL_mixer.h"
+
+
+#define CHANNELS 8
+#define MUSICFILE "data/music.s3m"
+#define MUSICVOLMUL 0.7f
+#define SFXVOLMUL 0.85f
+
+
+static int soundInitialized = 0, soundEnabled = 1, musicEnabled = 0;
+static Mix_Music *music;
+static int musicChn = -1;
+static float musicVolume = 1.0f;
+
+
+static void loadMusic()
+{
+ music = Mix_LoadMUS(MUSICFILE);
+ if (music == NULL)
+ {
+ errorMessage("Music Load Error", "Error loading file %s\nError: %s",
+ MUSICFILE, SDL_GetError());
+ exit(1);
+ }
+}
+
+
+void initSound()
+{
+ if (Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 2048) < 0)
+ {
+ errorMessage("Sound Disabled", "Unable to initialized audio! (%s)", SDL_GetError());
+ soundInitialized = soundEnabled = 0;
+ return;
+ }
+ soundInitialized = 1;
+ Mix_AllocateChannels(CHANNELS);
+
+ loadMusic();
+
+ setMusic(1);
+}
+
+
+void deinitSound()
+{
+ if (!soundInitialized)
+ return;
+
+ setMusic(0);
+
+ Mix_FreeMusic(music);
+
+ Mix_CloseAudio();
+}
+
+
+void setSound(int enabled)
+{
+ if (!soundInitialized)
+ return;
+
+ soundEnabled = enabled ? 1 : 0;
+}
+
+
+void setMusic(int enabled)
+{
+ if (!soundInitialized)
+ return;
+
+ if (enabled && !musicEnabled)
+ {
+ // turn music on
+ musicChn = Mix_FadeInMusic(music, -1, 1000);
+ musicEnabled = musicChn >= 0 ? 1 : 0; // not sure if this is needed
+ setMusicVolume(musicVolume);
+ }
+ else if (musicEnabled && !enabled)
+ {
+ // turn music off
+ Mix_FadeOutMusic(100);
+ musicEnabled = 0;
+ }
+}
+
+
+void setMusicVolume(float volume)
+{
+ if (!soundInitialized)
+ return;
+
+ musicVolume = volume;
+
+ if (musicEnabled)
+ Mix_Volume(musicChn, (int)(volume * MUSICVOLMUL * 128));
+}
+
+
+int getSoundEnabled()
+{
+ return soundEnabled;
+}
+
+
+int getMusicEnabled()
+{
+ return musicEnabled;
+}
More information about the Pkg-games-commits
mailing list