Back to index

supertuxkart  0.5+dfsg1
grand_prix_ending.cpp
Go to the documentation of this file.
00001 // $Id: grand_prix_ending.cpp 2111 2008-05-31 07:04:30Z cosmosninja $
00002 //
00003 //  SuperTuxKart - a fun racing game with go-kart
00004 //  Copyright (C) 2006 Eduardo Hernandez Munoz
00005 //
00006 //  This program is free software; you can redistribute it and/or
00007 //  modify it under the terms of the GNU General Public License
00008 //  as published by the Free Software Foundation; either version 2
00009 //  of the License, or (at your option) any later version.
00010 //
00011 //  This program is distributed in the hope that it will be useful,
00012 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 //  GNU General Public License for more details.
00015 //
00016 //  You should have received a copy of the GNU General Public License
00017 //  along with this program; if not, write to the Free Software
00018 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00019 
00020 #include <sstream>
00021 #include <string>
00022 
00023 #include <SDL/SDL.h>
00024 
00025 #include "loader.hpp"
00026 #include "sound_manager.hpp"
00027 #include "grand_prix_ending.hpp"
00028 #include "kart_properties_manager.hpp"
00029 #include "unlock_manager.hpp"
00030 #include "widget_manager.hpp"
00031 #include "race_manager.hpp"
00032 #include "game_manager.hpp"
00033 #include "user_config.hpp"
00034 #include "menu_manager.hpp"
00035 #include "kart_properties.hpp"
00036 #include "translation.hpp"
00037 #include "kart.hpp"
00038 #include "world.hpp"
00039 #include "scene.hpp"
00040 #if defined(WIN32) && !defined(__CYGWIN__)
00041 #  define snprintf _snprintf
00042 #endif
00043 
00044 enum WidgetTokens
00045 {
00046     WTOK_TITLE,
00047     WTOK_QUIT,
00048 
00049     WTOK_FIRSTKART
00050 };
00051 
00052 
00053 GrandPrixEnd::GrandPrixEnd()
00054         : m_kart(0)
00055 {
00056     // for some strange reasons plib calls makeCurrent() in ssgContext
00057     // constructor, so we have to save the old one here and restore it
00058     ssgContext* oldContext = ssgGetCurrentContext();
00059     m_context = new ssgContext;
00060     oldContext->makeCurrent();
00061 
00062     const unsigned int MAX_STR_LEN = 60;
00063     const unsigned int NUM_KARTS = race_manager->getNumKarts();
00064 
00065     int *scores   = new int[NUM_KARTS];
00066     int *position = new int[NUM_KARTS];
00067     double *race_time = new double[NUM_KARTS];
00068     for( unsigned int kart_id = 0; kart_id < NUM_KARTS; ++kart_id )
00069     {
00070         position[kart_id]  = kart_id;
00071         scores[kart_id]    = race_manager->getKartScore(kart_id);
00072         race_time[kart_id] = race_manager->getOverallTime(kart_id);
00073     }
00074 
00075     //Bubblesort
00076     bool sorted;
00077     do
00078     {
00079         sorted = true;
00080         for( unsigned int i = 0; i < NUM_KARTS - 1; ++i )
00081         {
00082             if( scores[i] < scores[i+1] || (scores[i] == scores[i+1] 
00083               && race_time[i] > race_time[i+1]))
00084             {
00085                 int tmp_score[2];
00086                 double tmp_time;
00087 
00088                 tmp_score[0] = position[i];
00089                 tmp_score[1] = scores[i];
00090                 tmp_time = race_time[i];
00091 
00092                 position[i] = position[i+1];
00093                 scores[i] = scores[i+1];
00094                 race_time[i] = race_time[i+1];
00095 
00096                 position[i+1] = tmp_score[0];
00097                 scores[i+1] = tmp_score[1];
00098                 race_time[i+1] = tmp_time;
00099 
00100                 sorted = false;
00101             }
00102         }
00103     } while(!sorted);
00104     
00105     static char output[MAX_MESSAGE_LENGTH];
00106     snprintf(output, sizeof(output),
00107         _("The winner is %s!"),race_manager->getKartName(position[0]).c_str());
00108     widget_manager->addWgt( WTOK_TITLE, 60, 10);
00109     widget_manager->showWgtRect(WTOK_TITLE);
00110     widget_manager->showWgtText(WTOK_TITLE);
00111     widget_manager->setWgtText(WTOK_TITLE, output);
00112     widget_manager->setWgtTextSize(WTOK_TITLE, WGT_FNT_LRG);
00113     widget_manager->breakLine();
00114 
00115     m_score = new char[MAX_STR_LEN*NUM_KARTS];
00116 
00117     for(unsigned int i=0; i < NUM_KARTS; ++i)
00118     {
00119         char sTime[20];
00120         TimeToString(race_time[i], sTime);
00121         sprintf((char*)(m_score + MAX_STR_LEN * i), "%d. %s %d %s",
00122             i + 1, race_manager->getKartName(position[i]).c_str(), scores[i], sTime );
00123 
00124         widget_manager->addWgt(WTOK_FIRSTKART + i, 40, 5);
00125         widget_manager->showWgtRect(WTOK_FIRSTKART + i);
00126         widget_manager->showWgtText(WTOK_FIRSTKART + i);
00127         widget_manager->setWgtText(WTOK_FIRSTKART + i,
00128             (char*)(m_score + MAX_STR_LEN * i));
00129         widget_manager->setWgtTextSize(WTOK_FIRSTKART + i, WGT_FNT_SML);
00130     widget_manager->breakLine();
00131     }
00132     const std::string KART_NAME = race_manager->getKartName(position[0]);
00133     const KartProperties* WINNING_KART = kart_properties_manager->getKart(KART_NAME);
00134     delete []scores;
00135     delete []position;
00136     delete []race_time;
00137 
00138     widget_manager->addWgt(WTOK_QUIT, 50, 7);
00139     widget_manager->activateWgt(WTOK_QUIT);
00140     widget_manager->showWgtRect(WTOK_QUIT);
00141     widget_manager->showWgtText(WTOK_QUIT);
00142     if(unlock_manager->getUnlockedFeatures().size()>0)
00143     {
00144         widget_manager->setWgtText(WTOK_QUIT, _("Continue"));
00145     }
00146     else
00147     {
00148         widget_manager->setWgtText(WTOK_QUIT, _("Back to the main menu"));
00149     }
00150 
00151     widget_manager->layout(WGT_AREA_TOP);
00152 
00153     m_kart = new ssgTransform;
00154     m_kart->ref();
00155     ssgEntity* kartentity = WINNING_KART->getModel();
00156     m_kart->addKid(kartentity);
00157 
00158     sound_manager->playSfx(SOUND_WINNER);
00159 
00160     m_clock = 0;
00161 
00162     //FIXME: this is taken from RaceMode::exit_race,
00163     //this should be organized better.
00164     scene->clear();
00165     delete world;
00166     world = 0;
00167     race_manager->m_active_race = false;
00168 
00169 }
00170 
00171 //-----------------------------------------------------------------------------
00172 GrandPrixEnd::~GrandPrixEnd()
00173 {
00174     widget_manager->reset();
00175     ssgDeRefDelete(m_kart);
00176 
00177     delete m_context;
00178     delete[] m_score;
00179 
00180     //The next line prevents textures like the background of the main menu from
00181     //going white after finishing the grandprix
00182     // FIXME: I think this is not necessary anymore after the
00183     //        texture bug fix (r733) - but I can't currently test this.
00184     loader->shared_textures.removeAll();
00185 }
00186 
00187 //-----------------------------------------------------------------------------
00188 
00189 void GrandPrixEnd::update(float dt)
00190 {
00191     m_clock += dt * 40.0f;
00192 
00193     glClearColor (0.1f, 0.1f, 0.1f, 1.0f);
00194     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00195 
00196     ssgContext* oldContext = ssgGetCurrentContext();
00197     m_context -> makeCurrent();
00198 
00199     // FIXME: A bit hackish...
00200     glViewport ( 0, 0, 800, 320);
00201 
00202     m_context -> setFOV ( 45.0f, 45.0f * 320.0f/800.0f ) ;
00203     m_context -> setNearFar ( 0.05f, 1000.0f ) ;
00204 
00205     sgCoord cam_pos;
00206     sgSetCoord(&cam_pos, 0, 0, 0, 0, 0, 0);
00207     m_context -> setCamera ( &cam_pos ) ;
00208 
00209     glEnable (GL_DEPTH_TEST);
00210     sgCoord trans;
00211     sgSetCoord(&trans, 0, 3, -.4f, m_clock, 0, 0);
00212     m_kart->setTransform (&trans) ;
00213     //glShadeModel(GL_SMOOTH);
00214     ssgCullAndDraw ( m_kart ) ;
00215     glViewport ( 0, 0, user_config->m_width, user_config->m_height ) ;
00216 
00217     glDisable (GL_DEPTH_TEST);
00218     oldContext->makeCurrent();
00219     BaseGUI::update(dt);
00220 }
00221 
00222 //-----------------------------------------------------------------------------
00223 void GrandPrixEnd::select()
00224 {
00225     // If a new feature was unlocked, display the new feature first
00226     // before returning to the main menu
00227     if(unlock_manager->getUnlockedFeatures().size()>0)
00228     {
00229         // This removes this menu from the stack, and adds the main menu. 
00230         // Then we push the new feature menu on top, so that it will be
00231         // displayed next, and on return the main menu is shown.
00232         menu_manager->switchToMainMenu();
00233         menu_manager->pushMenu(MENUID_UNLOCKED_FEATURE);
00234         return;
00235     }
00236 
00237     menu_manager->switchToMainMenu();
00238 }