Subversion Repositories AndroidProjects

Rev

Blame | Last modification | View Log | RSS feed

#pragma warning(disable:4244)
#pragma warning(disable:4018)

#include "GameOverEffect.h"
#include "Res.h"
#include "Board.h"
#include "SexyAppFramework/SexyAppBase.h"
#include "SexyAppFramework/Graphics.h"
#include "SexyAppFramework/Font.h"
#include "SexyAppFramework/Image.h"

using namespace Sexy;


//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
GameOverEffect::GameOverEffect()
{
        Init();
}

//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
void GameOverEffect::Init()
{
        mState = GameOverEffect::RED_FADE_IN;
        mAlpha = 0;
        mRed = 200;
        mRedHoldCount = 100;
        mRedChange = 4;
        mActive = false;
        mUpdateCnt = 0;
        mHue = 0;
        mCanInitFirstLevel = false;
        mFadeOut = false;
        mExplosion.clear();

        mText.clear();
        mText.push_back(Letter(_S("G")));
        mText.push_back(Letter(_S("A")));
        mText.push_back(Letter(_S("M")));
        mText.push_back(Letter(_S("E")));
        mText.push_back(Letter(_S(" O")));
        mText.push_back(Letter(_S("V")));
        mText.push_back(Letter(_S("E")));
        mText.push_back(Letter(_S("R")));

        mLines.clear();

        // Make as many lines as the screen is wide, and stagger them by a
        // random time up to 2 seconds, with speeds between 5 and 10 pixels per update.
        for (int i = 0; i < gSexyAppBase->mWidth; i++)
                mLines.push_back(DrippyLine((Rand() % 5) + 5, i, Rand() % 200));
}

//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
void GameOverEffect::Update(void)
{
        ++mUpdateCnt;

        // HSL is an alternative to specifying an RGB color format.
        // Using HSL lets us easily do the hyper blinking crazy weird
        // flashing effect commonly found in old games, such as Robotron.
        // Below, we increment the value by 7 per update. The &0xFF is an
        // easy way to clamp the value between 0 and 255 instead of having to
        // do a separate if (mHue > 255) mHue -= 255. This lets the value
        // rollover and keep cycling.
        mHue = (mHue + 7) & 0xFF;

        if (!mFadeOut)
        {
                // 10 times per second we create a new planet explosion animation and place it at a random
                // position within the grid's area.
                if (mUpdateCnt % 10 == 0)
                {
                        Explosion e;
                        e.mFrame = 0;
                        e.mX = GRID_START_X + (Rand() % (GRID_END_X - GRID_START_X - IMAGE_ATOMIC_EXPLOSION->GetCelWidth()));
                        e.mY = GRID_START_Y + (Rand() % (GRID_END_Y - GRID_START_Y - IMAGE_ATOMIC_EXPLOSION->GetCelHeight()));

                        mExplosion.push_back(e);                                                       
                }
               
                // Play a sound of a planet exploding ever 4th new planet. If we did this every single
                // planet, then 10 times per second you'd hear it, and trust me, it's really irritating.
                if ((mState == RED_FADE_IN) || (mState == RED_HOLD))
                        if (mUpdateCnt % 40 == 0)
                                gSexyAppBase->PlaySample(SOUND_EXPLOSION);

                // Update each explosion animation. When it's done, remove it.
                for (int i = 0; i < mExplosion.size(); i++)
                {
                        Explosion* e = &mExplosion[i];

                        // The animation runs at 20FPS, so every 5 updates step the frame.
                        if (mUpdateCnt % 5 == 0)
                        {
                                if (++e->mFrame >+ IMAGE_ATOMIC_EXPLOSION->GetCelWidth())
                                {
                                        mExplosion.erase(mExplosion.begin() + i);
                                        --i;
                                }
                        }
                }
        }

        if (mState == GameOverEffect::RED_FADE_IN)
        {
                // Slowly make the red effect become fully opaque to cover
                // the screen, while at the same time making the red value
                // pulse between 200 and 255.
                if (++mAlpha >= 255)
                {
                        mState = GameOverEffect::RED_HOLD;
                        mAlpha = 255;
                }
                else
                        PulseRed();
        }
        else if (mState == GameOverEffect::RED_HOLD)
        {
                // Hold for 1 second, the red pulsing effect for dramatic fun
                if (--mRedHoldCount <= 0)
                {
                        mState = GameOverEffect::SHOWING_LETTERS;
                        mUpdateCnt = 0;
                        gSexyAppBase->PlaySample(SOUND_GAME_OVER_TEXT);
                }
                else
                        PulseRed();
        }
        else if (mState == GameOverEffect::SHOWING_LETTERS)
        {
                // Start showing the GAME OVER letters. Fade out that fully
                // red screen, but still let it pulse while we do so.
                if (mAlpha > 0)
                {
                        PulseRed();
                        mAlpha -= 2;
                }

                // Increase the red value on each letter by 2 per update.
                // Once one letter has a red value of 50, let the next letter
                // after it begin to fade in. Stop looping if a letter has less
                // than 50 for its red value.
                bool done = true;
                for (int i = 0; i < mText.size(); i++)
                {
                        Letter* l = &mText[i];

                        if (l->mRed < 254)
                        {
                                done = false;
                                l->mRed += 2;
                        }

                        if (l->mRed < 50)
                        {
                                done = false;
                                break;
                        }
                }

                if (done)
                        mState = GameOverEffect::FADING_LETTERS;
        }
        else if (mState == GameOverEffect::FADING_LETTERS)
        {
                // Now make the lettesr fade out, starting with
                // the last letter. When a letter's red value drops
                // below 205, allow the letter before it to also begin
                // decreasing.
                bool done = true;
                for (int i = (int)mText.size() - 1; i >= 0; i--)
                {
                        Letter* l = &mText[i];

                        if (l->mRed > 1)
                        {
                                done = false;
                                l->mRed -= 2;
                        }

                        if (l->mRed > 205)
                        {
                                done = false;
                                break;
                        }
                }

                if (done)
                {
                        mAlpha = 0;
                        mState = GameOverEffect::SHOWING_STATS;
                        gSexyAppBase->PlaySample(SOUND_GAME_OVER_STATS);
                }

        }
        else if ((mState == GameOverEffect::DRIP_OUT) && !mFadeOut)
        {
                // move the drippy lines, but we aren't fading the screen out yet.
                bool alldone = true;
                for (int i = 0; i < mLines.size(); i++)
                {
                        // Once a line's starting delay has passed, it moves downward.
                        // Once it reaches the bottom of the screen, it begins to then
                        // move back upward. When all lines have moved upward, and thus the
                        // whole screen is totally opaque, we can begin the fade out sequence.
                        DrippyLine* dl = &mLines[i];
                        if (dl->mDelay > 0)
                        {
                                alldone = false;
                                --dl->mDelay;
                        }
                        else if (!dl->mDripUp)
                        {
                                alldone = false;
                                dl->mHeight += dl->mSpeed;
                                if (dl->mHeight >= gSexyAppBase->mHeight)
                                {
                                        dl->mHeight = 0;
                                        dl->mSpeed = 10;
                                        dl->mDripUp = true;
                                }
                        }
                        else if (dl->mDripUp && (dl->mHeight < gSexyAppBase->mHeight))
                        {
                                dl->mHeight += dl->mSpeed;
                                if (dl->mHeight >= gSexyAppBase->mHeight)
                                        dl->mHeight = gSexyAppBase->mHeight;
                                else
                                        alldone = false;
                        }

                }

                if (alldone)
                {
                        // Now that the screen is fully covered, allow the board to set up the first level
                        mCanInitFirstLevel = true;
                        mFadeOut = true;
                        mAlpha = 255;
                }
        }
        else if ((mState == GameOverEffect::DRIP_OUT) && mFadeOut)
        {
                if (--mAlpha <= 0)
                        mActive = false;
        }
}

///
//////////////////////////////////////////////////////////////////////////
void GameOverEffect::PulseRed()
{
        mRed += mRedChange;
        if (mRed >= 255)
        {
                mRed = 255;
                mRedChange = -mRedChange;
        }
        else if (mRed <= 200)
        {
                mRed = 200;
                mRedChange = -mRedChange;
        }
}

//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
void GameOverEffect::Draw(Graphics* g)
{
        // Draw explosions for every state except the final fade out
        if (!mFadeOut)
        {
                for (int i = 0; i < mExplosion.size(); i++)
                {
                        Explosion* e = &mExplosion[i];
                        g->DrawImageCel(IMAGE_ATOMIC_EXPLOSION, e->mX, e->mY, e->mFrame);
                }
        }

        if ((mState == GameOverEffect::RED_FADE_IN) || (mState == GameOverEffect::RED_HOLD))
        {
                g->SetColor(Color(mRed, 0, 0, mAlpha));
                g->FillRect(0, 0, gSexyAppBase->mWidth, gSexyAppBase->mHeight);
        }
        else if ((mState == GameOverEffect::SHOWING_LETTERS) || (mState == GameOverEffect::FADING_LETTERS))
        {
                g->SetFont(FONT_HUNGARR);
                int x = gSexyAppBase->mWidth / 2 - FONT_HUNGARR->StringWidth(_S("GAME OVER")) / 2;
                int y = gSexyAppBase->mHeight / 2;

                for (int i = 0; i < mText.size(); i++)
                {
                        Letter* l = &mText[i];
                        if (l->mRed > 0)
                        {
                                g->SetColor(Color(l->mRed, 0, 0));
                                g->DrawString(l->mChar, x, y);
                                x += FONT_HUNGARR->StringWidth(l->mChar);
                        }
                }

                if (mAlpha > 0)
                {
                        g->SetColor(Color(mRed, 0, 0, mAlpha));
                        g->FillRect(0, 0, gSexyAppBase->mWidth, gSexyAppBase->mHeight);
                }
        }
        else if (mState == GameOverEffect::SHOWING_STATS)
        {              
                g->DrawImage(IMAGE_HUNGARR_LOGO, gSexyAppBase->mWidth / 2 - IMAGE_HUNGARR_LOGO->mWidth / 2, 10);

                g->SetFont(FONT_HUNGARR);
                g->SetColor(Color::White);
                int rightX = gSexyAppBase->mWidth / 2;
                int y = 100;
                SexyString s;
                int strWidth;

                s = _S("FINAL SCORE: ");
                strWidth = FONT_HUNGARR->StringWidth(s);
                g->DrawString(s, rightX - strWidth, y);
                g->SetColor(Color(255, 0, 0));
                g->DrawString(CommaSeperate(mStats.mScore), rightX, y);
               
                g->SetColor(Color::White);
                y += FONT_HUNGARR->GetHeight();
                s = _S("LEVEL REACHED: ");
                strWidth = FONT_HUNGARR->StringWidth(s);
                g->DrawString(s, rightX - strWidth, y);
                g->SetColor(Color(255, 0, 0));
                g->DrawString(StrFormat(_S("%d"), mStats.mLevel), rightX, y);

                g->SetColor(Color::White);
                y += FONT_HUNGARR->GetHeight();
                s = _S("TOTAL PLANETS EATEN: ");
                strWidth = FONT_HUNGARR->StringWidth(s);
                g->DrawString(s, rightX - strWidth, y);
                g->SetColor(Color(255, 255, 0));
                g->DrawString(StrFormat(_S("%d"), mStats.mNumPlanetsEaten), rightX, y);

                g->SetColor(Color::White);
                y += FONT_HUNGARR->GetHeight();
                s = _S("TOTAL PEOPLE EATEN: ");
                strWidth = FONT_HUNGARR->StringWidth(s);
                g->DrawString(s, rightX - strWidth, y);
                g->SetColor(Color(255, 255, 0));
                g->DrawString(CommaSeperate(mStats.mPopulationConsumed), rightX, y);

                g->SetColor(Color::White);
                y += FONT_HUNGARR->GetHeight();
                s = _S("TASTIEST PLANET: ");
                strWidth = FONT_HUNGARR->StringWidth(s);
                g->DrawString(s, rightX - strWidth, y);
                g->SetColor(Color(0, 255, 0));
                g->DrawString(mStats.mFavoritePlanet, rightX, y);


                g->SetColor(Color::White);
                y += FONT_HUNGARR->GetHeight();
                s = _S("EXPORT EATEN MOST: ");
                strWidth = FONT_HUNGARR->StringWidth(s);
                g->DrawString(s, rightX - strWidth, y);
                g->SetColor(Color(0, 255, 0));
                g->DrawString(mStats.mFavoriteExport, rightX, y);
        }
        else if (mState == GameOverEffect::DRIP_OUT)
        {
                if (!mFadeOut)
                {
                        // This is how we convert an HSL value to an RGB value, which we have to
                        // do to specify the color for the graphics object. The function HSLToRGB
                        // takes as parameters: hue, saturation, luminance. We want to leave the
                        // saturation at max and luminance at half for our particular example.
                        // The returned value is ANDed with 0xFFFFFFFF to clamp the values for
                        // the alpha, red, green, and blue to the valid region of 0 to 255.
                        Color hue = gSexyAppBase->HSLToRGB(mHue, 255, 128) & 0xFFFFFFFF;
                        for (int i = 0; i < mLines.size(); i++)
                        {
                                DrippyLine* dl = &mLines[i];
                                if (!dl->mDripUp && (dl->mDelay == 0))
                                {
                                        // Draw a black line, with its bottommost pixel using the HSL color
                                        g->SetColor(Color(0, 0, 0));
                                        g->DrawRect(Rect(dl->mX, 0, 1, dl->mHeight - 1));
                                        g->SetColor(hue);
                                        g->DrawRect(Rect(dl->mX, dl->mHeight, 1, 1));
                                }
                                else if (dl->mDelay == 0)
                                {
                                        // Moving up, draw the line in HSL and the rest in black
                                        if (dl->mHeight < gSexyAppBase->mHeight)
                                        {
                                                g->SetColor(Color(0, 0, 0));
                                                g->DrawRect(Rect(dl->mX, 0, 1, gSexyAppBase->mHeight - dl->mHeight));
                                        }

                                        g->SetColor(hue);
                                        g->DrawRect(Rect(dl->mX, gSexyAppBase->mHeight - dl->mHeight, 1, dl->mHeight));
                                }
                        }
                }
                else
                {
                        // We AND the color with 0xFFFFFF instead of 0xFFFFFFFF. Then, we OR it with the alpha value
                        // that we're fading out with shifted left 24 bits.
                        //      This then sticks the alpha value, which changes over time,
                        // into our HSL color. As you may recall from previous demos, the actual color
                        // structure is 32 bit, and looks like this in binary form:
                        //      AAAA RRRR GGGG BBBB  Where A,R,G,B are alpha, red, green, blue.
                        Color hue = (gSexyAppBase->HSLToRGB(mHue, 255, 128) & 0xFFFFFF) | (mAlpha << 24);
                        g->SetColor(hue);
                        g->FillRect(0, 0, gSexyAppBase->mWidth, gSexyAppBase->mHeight);
                }
        }
}

//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
bool GameOverEffect::CanInitFirstLevel(void)
{
        if (mCanInitFirstLevel)
        {
                mCanInitFirstLevel = false;            
                return true;
        }

        return false;
}

//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
bool GameOverEffect::HideBoard()
{
        return (mState == GameOverEffect::SHOWING_LETTERS) ||
                        (mState == GameOverEffect::RED_HOLD) ||
                        (mState == GameOverEffect::FADING_LETTERS) ||
                        (mState == GameOverEffect::SHOWING_STATS) ||
                        ((mState == GameOverEffect::DRIP_OUT) && !mFadeOut);
}

//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
void GameOverEffect::DoneViewingStats()
{
        mState = DRIP_OUT;
        gSexyAppBase->PlaySample(SOUND_GAME_OVER_CLICK);
        gSexyAppBase->PlaySample(SOUND_GAME_OVER_RESTART);
}