Logo Search packages:      
Sourcecode: zaz version File versions  Download package

mainmenu.cpp

/*
 * Zaz
 * Copyright (C) Remigiusz Dybka 2009 <remigiusz.dybka@gmail.com>
 *
 Zaz 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 3 of the License, or
 (at your option) any later version.

 Zaz 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, see <http://www.gnu.org/licenses/>.
 */

#include "mainmenu.h"
#include "textureloader.h"
#include "game.h"
#include "sample.h"
#include "gameloop.h"

MainMenu::MainMenu(Scenes::Settings *settings, SDL_Surface *surf, uint fps)
        :Scenes::Scene(settings, surf, fps), currentMenu(&startMenu),
        menuLev(settings->getCFilename("menu"), true), nBallPaths(menuLev.paths.size() - 1), music(NULL),
        renderHiscores(true), showCredits(false), showBrowser(false), oldFullscreen(settings->getb("fullscreen", false)),
        oldRes(settings->get("resolution", "")), startup(true), browserSelectedLevel(-1)
{
    startMenu.Add(new GenericMenuItem(_("Start game"), startMenuStartHandler, this));
    startMenu.Add(new GenericMenuItem(_("Options"), startMenuOptionsHandler, this));
    startMenu.Add(new GenericMenuItem(_("Credits"), startMenuCreditsHandler, this));
    startMenu.Add(new GenericMenuItem(_("Exit"), startMenuExitHandler, this));

    startMenu.SetDimensions(60, 40, 40);

    std::vector<std::string>resolutions;

    for (uint m = 0; screenModes[m]; ++m)
    {
        stringstream sm;
        sm << screenModes[m]->w << "x" << screenModes[m]->h;

        resolutions.push_back(sm.str());
    }

    optionsMenu.Add(new OptionMenuItem(_("Resolution"), resolutions, settings, "resolution"));
    optionsMenu.Add(new BooleanMenuItem(_("Fullscreen"), settings, "fullscreen"));
    optionsMenu.Add(new BooleanMenuItem(_("Show FPS"), settings, "showFps"));
    optionsMenu.Add(new ValueMenuItem(_("Mouse sensivity"), 1, 10, settings, "mouseSensivity"));
    optionsMenu.Add(new ValueMenuItem(_("SFX volume"), 0, 100, settings, "sfxVolume"));
    optionsMenu.Add(new ValueMenuItem(_("Music volume"), 0, 100, settings, "musicVolume"));
    optionsMenu.Add(new GenericMenuItem(_("Back to main menu"), optionsMenuBackHandler, this));

    optionsMenu.SetDimensions(55, 45, 60);

    creditsMenu.Add(new GenericMenuItem(_("Back"), optionsMenuBackHandler, this));
    creditsMenu.SetDimensions(30, 10, 40);


    browserMenu.Add(new GenericMenuItem(_("Back"), optionsMenuBackHandler, this));
    browserMenu.Add(new GenericMenuItem("<<", browserMenuRightHandler, this));
    browserMenu.Add(new GenericMenuItem(">>", browserMenuLeftHandler, this));
    browserMenu.SetDimensions(30, 10, 40);


    browserMenu.items[1]->x = 10;
    browserMenu.items[1]->width = 10;
    browserMenu.items[1]->y = 15;

    browserMenu.items[2]->x = 80;
    browserMenu.items[2]->width = 10;
    browserMenu.items[2]->y = 15;

    for (int p = 0; p < nBallPaths; p++)
    {
        bp.push_back(BallPath(menuLev.paths[p + 1], ballText, 0));
        bp[p].state.feedRate = 2;
        bp[p].state.colors = 8;
        bp[p].state.ballsToDraw = -1;
        bp[p].state.ballsFromStart = 0;
    }
}

void MainMenu::RenderStartupProgress()
{
    float pbarwidth = 80;
    float pbarheight = 5;

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity( );
    glTranslated((100 - pbarwidth) / 2, (vheight + pbarheight) / 2, 0);

    glBegin(GL_QUADS);
    glColor3d( .1, .1, .7);
    glVertex3d(0, 0, 0);
    glVertex3d(0, -pbarheight, 0);
    glColor3d( 0, 0, 0.5);
    glVertex3d((startupProgress / startupProgressSteps) * pbarwidth, -pbarheight, 0);
    glVertex3d((startupProgress / startupProgressSteps) * pbarwidth, 0, 0);
    glEnd();

    glColor3d( 0, 0, 0.5);
    glBegin(GL_LINE_STRIP);
    glVertex3d(0, 0, 0);
    glVertex3d(0, -pbarheight, 0);
    glVertex3d(pbarwidth, -pbarheight, 0);
    glVertex3d(pbarwidth, 0, 0);
    glVertex3d(0, 0, 0);
    glEnd();

    startupProgress++;
    glFlush();
    SDL_GL_SwapBuffers();
}

void MainMenu::LoadTextures()
{
    bool found = true;
    int f = 1;

    while (found)
    {
        std::stringstream ss;
        ss << "level" << f << ".lvl";

        std::ifstream inph(settings->getCFilename(ss.str()));
        if (inph)
        {
            levels.push_back(settings->getCFilename(ss.str()));
            ++f;
        }
        else
        {
            found = false;
        }
    }

    startupProgressSteps = (float)levels.size() + 16;
    startupProgress = 0;

    // load the textures
    ballText[0] = LoadTexture("balls1.png");
    RenderStartupProgress();
    ballText[1] = LoadTexture("balls2.png");
    RenderStartupProgress();
    ballText[2] = LoadTexture("balls3.png");
    RenderStartupProgress();
    ballText[3] = LoadTexture("balls4.png");
    RenderStartupProgress();
    ballText[4] = LoadTexture("balls5.png");
    RenderStartupProgress();
    ballText[5] = LoadTexture("balls6.png");
    RenderStartupProgress();
    ballText[6] = LoadTexture("balls7.png");
    RenderStartupProgress();
    ballText[7] = LoadTexture("balls8.png");
    RenderStartupProgress();

    ballText[8] = LoadTexture("bonus1.png");
    RenderStartupProgress();
    ballText[9] = LoadTexture("bonus2.png");
    RenderStartupProgress();
    ballText[10] = LoadTexture("bonus3.png");
    RenderStartupProgress();
    ballText[11] = LoadTexture("bonus4.png");
    RenderStartupProgress();
    ballText[12] = LoadTexture("bonus5.png");
    RenderStartupProgress();
    ballText[13] = LoadTexture("explosion.png");
    RenderStartupProgress();

    logoTex = LoadTexture("logo.png");
    RenderStartupProgress();
    logoGpl = LoadTexture ("gpl3.png");
    RenderStartupProgress();

    // level thumbs

    for (uint f = 0; f < levels.size(); f++)
    {
        string texname = levels[f].lev.savePhilename;
        texname = texname.substr(0, texname.find_last_of("."));

//          if (settings->getb();
        string setname = texname;
        texname = texname + "_thumb.png";
        levels[f].tex = LoadTextureFile (texname.c_str());

        if (f < levels.size() - 1)
        {
            setname = setname.substr(setname.find_last_of(SEPARATOR) + 1);
            setname += "_completed";

            if (settings->getb(setname, false))
            {
                levels[f+1].locked = false;
            }
        }


        RenderStartupProgress();
    }

    levels[0].locked = false;

    RenderStartupProgress();
}


void MainMenu::StartMusic()
{
    music = (Scenes::Sample *)new Scenes::StreamingOggSample("mus1.ogg");
    mixer->EnqueueSample(music, 100, 0, true);
}

void MainMenu::StopMusic()
{
    mixer->DisposeSample(music);
}


void browserMenuLeftHandler(void *ptr)
{
    MainMenu *p = (MainMenu *)ptr;
    p->browserScrollOffsetDest+=p->browserNLevelsPerPage;
    if (p->browserScrollOffsetDest > (int)(p->levels.size() - p->browserNLevelsPerPage))
        p->browserScrollOffsetDest = p->levels.size() - p->browserNLevelsPerPage;
}

void browserMenuRightHandler(void *ptr)
{
    MainMenu *p = (MainMenu *)ptr;
    p->browserScrollOffsetDest-=p->browserNLevelsPerPage;
    if (p->browserScrollOffsetDest < 0)
        p->browserScrollOffsetDest = 0;

}

void optionsMenuBackHandler(void *ptr)
{
    ((MainMenu*)ptr)->currentMenu = &((MainMenu*)ptr)->startMenu;
    ((MainMenu*)ptr)->renderHiscores = true;
    ((MainMenu*)ptr)->showCredits = false;
    ((MainMenu*)ptr)->showBrowser = false;

    wantReinit = false;

    if (((MainMenu*)ptr)->oldFullscreen != ((MainMenu*)ptr)->settings->getb("fullscreen", false))
        wantReinit = true;

    if (((MainMenu*)ptr)->oldRes != ((MainMenu*)ptr)->settings->get("resolution", ""))
        wantReinit = true;

    if (wantReinit)
        ((MainMenu*)ptr)->quit = true;
};

void startMenuOptionsHandler(void *ptr)
{
    ((MainMenu*)ptr)->oldFullscreen = ((MainMenu*)ptr)->settings->getb("fullscreen", false);
    ((MainMenu*)ptr)->oldRes = ((MainMenu*)ptr)->settings->get("resolution", "");

    ((MainMenu*)ptr)->currentMenu = &((MainMenu*)ptr)->optionsMenu;
    ((MainMenu*)ptr)->renderHiscores = true;
};

void startMenuCreditsHandler(void *ptr)
{
    ((MainMenu*)ptr)->currentMenu = &((MainMenu*)ptr)->creditsMenu;
    ((MainMenu*)ptr)->renderHiscores = false;
    ((MainMenu*)ptr)->showCredits = true;
};

void startMenuExitHandler(void *ptr)
{
    ((MainMenu*)ptr)->quit = true;
};

void startMenuStartHandler(void *ptr)
{
    MainMenu *p = (MainMenu *)ptr;
    p->browserScrollOffset = -5.0;
    p->browserScrollOffsetDest = 0;
    p->browserSelectedLevel = -1;
    p->showBrowser = true;
    p->renderHiscores = false;
    p->currentMenu = &((MainMenu*)ptr)->browserMenu;


    /*MainMenu *p = (MainMenu *)ptr;
    p->StopMusic();
    GameLoop(p->settings, p->surface, p->ballText).Run();
    p->resync = true;
    p->StartMusic();
    p->GLSetup();
    SDL_ShowCursor(SDL_ENABLE);
    SDL_WM_GrabInput(SDL_GRAB_OFF);
     */
};

MainMenu::~MainMenu()
{
    glDeleteTextures(1, &logoTex);
    glDeleteTextures(1, &logoGpl);
    glDeleteTextures(14, ballText);

    for (uint f = 0; f < levels.size(); f++)
        glDeleteTextures(1, &levels[f].tex);
}

void MainMenu::GLSetup()
{
    int width = surface->w;
    int height = surface->h;

    /* Our shading model--Gouraud (smooth). */
    glShadeModel( GL_SMOOTH );

    /* Culling. */
    glCullFace( GL_BACK );
    glFrontFace( GL_CCW );
    glEnable( GL_CULL_FACE );
    glEnable(GL_DEPTH_TEST);
    glEnable( GL_ALPHA_TEST );
    glAlphaFunc(GL_GREATER, 0.0);
    glEnable(GL_LINE_SMOOTH);

    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
    glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
    glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);

    glClearColor( .1f, .1f, .7f, 1.0f );
    glViewport( 0, 0, width, height);
    glMatrixMode( GL_PROJECTION );
    glLoadIdentity( );

    vwidth = 100 * (640.0/480.0);
    vleft = (100 - vwidth) / 2;
    vheight = 100.0;

    glOrtho(vleft, vwidth + vleft, 0, 100, -100, 100);
    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
}

void MainMenu::Render(ulong frame)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glColor3f(1.0, 1.0, 1.0);
    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity( );

    for (int p = 0; p < nBallPaths; ++p)
    {
        bp[p].Render();
    }

    // logo
    glLoadIdentity( );
    glPushMatrix();
    glEnable(GL_TEXTURE_2D);
    glTranslated(vleft + 5, 95, 5);
    glBindTexture(GL_TEXTURE_2D, logoTex);
    glScalef(80, 48, 5);
    glBegin(GL_QUADS);
    glTexCoord2d(0, 0);
    glVertex3d(0, 0, 0);
    glTexCoord2d(0, 1);
    glVertex3d(0, -1, 0);
    glTexCoord2d(1, 1);
    glVertex3d(1, -1, 0);
    glTexCoord2d(1, 0);
    glVertex3d(1, 0, 0);
    glEnd();
    glDisable(GL_TEXTURE_2D);
    glPopMatrix();

    currentMenu->Render();

    if ((renderHiscores) && (!hiScores.scores.empty()))
    {
        glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

        uint nHigh = hiScores.scores.size();
        glPushMatrix();
        glTranslatef(18, 42, 5);
        glScalef(0.15f, 0.15f, 0.15f);
        glColor4d(1.0, 1.0, 1.0, 1.0);

        font->Render(_("Hall of Fame"), -1);
        glPopMatrix();

        float y = 35;
        for (uint f = 0; f < 10 && f < nHigh; f++)
        {
            char buff[256];

            glPushMatrix();
            glTranslatef(0, y, 5);
            glScalef(0.1f, 0.1f, 0.1f);
            glColor4d(1.0, 1.0, 1.0, 0.7);

            sprintf(buff, "%2d. %05d %s", f + 1, hiScores.scores[f].score, hiScores.scores[f].name.c_str());
            font->Render(buff, -1);
            glPopMatrix();

            y-=3;

        }

    }

    if (showCredits)
    {
        glColor4f(1.0, 1.0, 1.0, 1.0);
        CenterMsg(_("code, gfx, snd & design:"), 46, font, 0.08);
        CenterMsg(_("Remigiusz Dybka"), 43.5, font, 0.1);
        CenterMsg(_("[remigiusz.dybka@gmail.com]"), 41.5, font, 0.08);

        CenterMsg(_("music:"), 37, font, 0.08);
        CenterMsg(_("Nine Inch Nails"), 34.5, font, 0.1);
        CenterMsg(_("[http://nin.com] Released under Creative Commons Attribution Non-Commercial Share Alike License"), 32.5, font, 0.08);

        CenterMsg(_("quality assurance:"), 28, font, 0.08);
        CenterMsg(_("Irena Klon & Kamil Krzyspiak"), 25.5, font, 0.1);

        glLoadIdentity();
        glEnable(GL_TEXTURE_2D);
        glTranslatef(50, 18, 5);
        glBindTexture(GL_TEXTURE_2D, logoGpl);
        glScalef(20, 10, 1);
        glBegin(GL_QUADS);
        glTexCoord2d(0, 0);
        glVertex3d(-.5, .5, 0);
        glTexCoord2d(0, 1);
        glVertex3d(-.5, -.5, 0);
        glTexCoord2d(1, 1);
        glVertex3d(.5, -.5, 0);
        glTexCoord2d(1, 0);
        glVertex3d(.5, .5, 0);
        glEnd();
        glDisable(GL_TEXTURE_2D);
    }

    if (showBrowser)
    {
        int lstart = (int)iround(browserScrollOffset) - 1;
        if (lstart < 0)
            lstart = 0;

        int lend = lstart + browserNLevelsPerPage + browserNLevelsPerPage;
        if (lend > (int)levels.size())
            lend = levels.size();

        double tw = (100.0 - double((browserThumbSpacing * (browserNLevelsPerPage - 1)))) / browserNLevelsPerPage;
        double th = tw / (640.0/480.0);

        double xmv = -(browserScrollOffset - lstart) * (tw + browserThumbSpacing);

        double xx = 0;
        double spc = 0;
        browserSelectedLevel = -1;
        for (int f = lstart; f < lend; f++)
        {
            glLoadIdentity();
            glTranslated(xx * tw + spc + xmv, 30 - (th / 2), 5);

            if ((mx > xx * tw + spc + xmv) &&
                    (mx < xx * tw + spc + xmv + tw) &&
                    (my > 30 - (th / 2)) &&
                    (my < 30 + (th / 2)))
            {
                if (!levels[f].locked && iround(browserScrollOffset) >= 0)
                    browserSelectedLevel = f;
            }

            glColor4d(.7, .7, .7, 1.0);
            if (browserSelectedLevel == f)
            {
                glColor4d(1.0, 1.0, 1.0, 1.0);
            }
            glEnable(GL_TEXTURE_2D);
            glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
            glBindTexture(GL_TEXTURE_2D, levels[f].tex);
            glBegin(GL_QUADS);
            glTexCoord2d(0, 0);
            glVertex3d(0, th, 0);
            glTexCoord2d(0, 1);
            glVertex3d(0, 0, 0);
            glTexCoord2d(1, 1);
            glVertex3d(tw, 0, 0);
            glTexCoord2d(1, 0);
            glVertex3d(tw, th, 0);
            glEnd();
            glDisable(GL_TEXTURE_2D);
            glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

            glLoadIdentity();
            glTranslated(xx * tw + spc + xmv, 30 - (th / 2), 7);
            glColor4d(0, 0, 0, 1);
            glLineWidth(2.0);
            glBegin(GL_LINE_STRIP);
            glVertex3d(0, 0, 0);
            glVertex3d(0, th, 0);
            glVertex3d(tw, th, 0);
            glVertex3d(tw, 0, 0);
            glVertex3d(0, 0, 0);
            glEnd();

            double size = 0.08;
            glLoadIdentity( );
            glColor4d(1.0, 1.0, 1.0, 1);
            char levelName[256];
            sprintf(levelName, "%s", levels[f].lev.name.c_str());

            FTBBox b = font->BBox(gettext(levelName));
            double txtw = b.Upper().X() / (1.0 / size);
            glTranslated((xx * tw + spc) + (tw / 2) - (txtw / 2) + xmv, 16, 5);
            glScaled(size, size, size);

            glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
            font->Render(gettext(levelName));
            glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

            if (levels[f].locked)
            {
                char lockedTxt[256];

                sprintf(lockedTxt, "%s", _("locked"));
                size = 0.3;
                glLoadIdentity( );
                glColor4d(1.0, 0, 0, 1);
                b = font->BBox(lockedTxt);
                txtw = b.Upper().X() / (1.0 / size);
                glTranslated((xx * tw + spc) + (tw / 2) - (txtw / 2) + xmv, 28, 7);
                glScaled(size, size, size);

                glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
                font->Render(lockedTxt);
                glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
            }



            spc += browserThumbSpacing;
            xx += 1.0;
        }
    }
}

void MainMenu::Logic(ulong frame)
{
    if (startup)
    {
        GLSetup();
        LoadTextures();
        startup = false;
    }

    if (music == NULL)
        StartMusic ();

    if (!events.empty)
    {
        if (events.keyDown.size() > 0)
            for (vector<SDLKey>::iterator i = events.keyDown.begin(); i != events.keyDown.end(); ++i)
            {
                if (*i == SDLK_ESCAPE)
                {
                    if (currentMenu == &startMenu)
                    {
                        quit = true;
                    }
                    else
                    {
                        currentMenu = &startMenu;
                        renderHiscores = true;
                        showBrowser = false;
                    }
                }
            }


        mx = (vwidth * events.mouseX) + vleft;
        my = vheight - (vheight * events.mouseY);
        bool click = false;

        if (events.buttDown[0])
            click = true;

        currentMenu->Logic(mx, my, click);

        if (showBrowser && browserSelectedLevel > -1 && click)
        {
            currentMenu = &startMenu;
            renderHiscores = true;
            showBrowser = false;

            StopMusic();
            GameLoop(settings, surface, ballText, browserSelectedLevel).Run();
            resync = true;
            for (uint f = 0; f < levels.size(); f++)
            {
                string setname = levels[f].lev.savePhilename;
                setname = setname.substr(0, setname.find_last_of("."));
                setname = setname.substr(setname.find_last_of(SEPARATOR) + 1);
                setname += "_completed";

                if (f < levels.size() - 1)
                {
                    if (settings->getb(setname, false))
                    {
                        levels[f+1].locked = false;
                    }
                }
            }


            StartMusic();
            GLSetup();
            SDL_ShowCursor(SDL_ENABLE);
            SDL_WM_GrabInput(SDL_GRAB_OFF);
        }
    }

    for (int p = 0; p < nBallPaths; ++p)
    {
        bp[p].state.ballOut = false;
        bp[p].Logic();
    }

    if (showBrowser)
    {
        browserScrollOffset = browserScrollOffset + (browserScrollOffsetDest - browserScrollOffset) / 20.0;
    }
}

void MainMenu::CenterMsg(string msg, double y, FTFont *font, double size)
{
    glLoadIdentity( );
    FTBBox b = font->BBox(msg.c_str());
    double tw = b.Upper().X() / (1.0 / size);
    glTranslated((100 - tw) / 2, y, 5);
    glScaled(size, size, size);

    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
    font->Render(msg.c_str());
    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
}


Generated by  Doxygen 1.6.0   Back to index