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