Back to index

extremetuxracer  0.5beta
hud.cpp
Go to the documentation of this file.
00001 /* 
00002  * PPRacer 
00003  * Copyright (C) 2004-2005 Volker Stroebel <volker@planetpenguin.de>
00004  *
00005  * Copyright (C) 1999-2001 Jasmin F. Patry
00006  * 
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  * 
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  * 
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00020  */
00021 
00022 #include "gl_util.h"
00023 #include "fps.h"
00024 #include "phys_sim.h"
00025 #include "course_mgr.h"
00026 #include "game_config.h"
00027 #include "hud.h"
00028 
00029 #include "stuff.h"
00030 #include "game_mgr.h"
00031 
00032 #include "ppgltk/ui_mgr.h"
00033 #include "ppgltk/alg/defs.h"
00034 
00035 HUD HUD1;
00036 
00037 HUD::Element::Element()
00038  : type(-1), 
00039    x(0), y(0),
00040    font(NULL),
00041    texture(0),
00042    texture2(0),
00043    width(0), height(0),
00044    size(0),
00045    angle(0)   
00046 {
00047 }
00048 
00049 HUD::HUD()
00050 {
00051        m_numElements=0;     
00052 }
00053 
00054 void
00055 HUD::reset()
00056 {
00057        m_numElements=0;
00058        initGauge();
00059 }
00060 
00061 bool
00062 HUD::add(Element newElement){
00063        if( m_numElements < HUD_MAX_ITEMS){
00064               m_element[m_numElements] = newElement;
00065               m_numElements++;
00066               return true;
00067        }else{
00068               return false;
00069        }      
00070 }
00071        
00072 bool
00073 HUD::update(const int i, Element newElement){
00074        if( m_numElements > i ){
00075               m_element[i] = newElement;
00076               return true;  
00077        }else{
00078               //element i not available
00079               return false;
00080        }      
00081 }
00082 
00083 void
00084 HUD::draw(Player& plyr)
00085 {
00086        UIMgr.setupDisplay();
00087        set_gl_options( TEXFONT );
00088        
00089        for(int i=0; i<m_numElements; i++){       
00090               switch(m_element[i].type){
00091                      case 0:
00092                             text(i);
00093                             break;
00094                      case 1:
00095                             fps(i);
00096                             break;
00097                      case 2:
00098                             herring(i,plyr.herring);
00099                             break;
00100                      case 3:
00101                             image(i);
00102                             break;
00103                      case 4:
00104                             time(i);
00105                             break; 
00106                      case 5:
00107                             {
00108                             pp::Vec3d vel = plyr.vel;
00109                      speed(i,vel.normalize()* M_PER_SEC_TO_KM_PER_H);
00110                             }
00111                             break;
00112                      case 6:
00113                             {
00114                             pp::Vec3d vel = plyr.vel;
00115                             gauge(i,vel.normalize()* M_PER_SEC_TO_KM_PER_H,plyr.control.jump_amt);
00116                             }
00117                             break;
00118                      case 7:
00119                             bar(i,plyr.control.jump_amt);
00120                             break;
00121                      case 8:
00122                             {
00123                             pp::Vec3d vel = plyr.vel;
00124                             bar(i,vel.normalize()* M_PER_SEC_TO_KM_PER_H/135);
00125                             }      
00126                             break;
00127                      case 9:
00128                             coursePercentage(i);
00129                             break;
00130                      case 10:
00131                             if ( getparam_display_course_percentage() ){            
00132                                    bar(i,players[0].getCoursePercentage()/100);
00133                             }
00134                             break;
00135             case 11:
00136                 objectives_time(i,false);
00137                 break;
00138             case 12:
00139                 objectives_herring(i,false);
00140                 break;
00141             case 13:
00142                 objectives_time(i,true);
00143                 break;
00144             case 14:
00145                 objectives_herring(i,true);
00146                 break;
00147            case 15:
00148               icon_time(i);
00149               break;
00150            case 16:
00151               icon_herring(i);
00152               break;
00153               }
00154        }
00155 }
00156 
00157 void
00158 HUD::text(const int i)
00159 {
00160     if(m_element[i].font){
00161               fix_xy(m_element[i].x, m_element[i].y,
00162                         m_element[i].height, m_element[i].width);
00163               
00164               m_element[i].font->draw(m_element[i].string.c_str(),
00165                                m_element[i].x, m_element[i].y);              
00166        }
00167 }
00168 
00169 void
00170 HUD::fps(const int i)
00171 {
00172        if ( ! getparam_display_fps() ) {
00173               return;
00174     }
00175        
00176     if(m_element[i].font){
00177               char string[BUFF_LEN];
00178               sprintf( string, m_element[i].string.c_str(), fpsCounter.get() );
00179               
00180               pp::Font::utf8ToUnicode(m_element[i].u_string,string);
00181               int width = int(m_element[i].font->advance(m_element[i].u_string));
00182               
00183               fix_xy(m_element[i].x,m_element[i].y,m_element[i].height,width);
00184               m_element[i].font->draw(m_element[i].u_string, m_element[i].x, m_element[i].y);            
00185        }
00186 }
00187 
00188 void
00189 HUD::herring(const int i, const int herring_count)
00190 {
00191        if(m_element[i].font){
00192               char string[BUFF_LEN];
00193               sprintf( string, m_element[i].string.c_str(), herring_count );
00194               
00195               pp::Font::utf8ToUnicode(m_element[i].u_string,string);
00196               int width = int(m_element[i].font->advance(m_element[i].u_string));
00197               
00198               fix_xy(m_element[i].x,m_element[i].y,m_element[i].height,width);
00199               m_element[i].font->draw(m_element[i].u_string, m_element[i].x, m_element[i].y);            
00200        }
00201 }
00202 
00203 void
00204 HUD::image(const int i)
00205 {
00206        if(!m_element[i].texture) return;
00207 
00208        if ( !getparam_display_course_percentage() && m_element[i].texture == 47) {
00209               return;
00210        }
00211 
00212     glColor3f( 1.0, 1.0, 1.0 );
00213 
00214     glBindTexture( GL_TEXTURE_2D, m_element[i].texture );
00215 
00216        fix_xy( m_element[i].x, m_element[i].y, m_element[i].height, m_element[i].width);
00217        
00218     glPushMatrix();
00219     {
00220        glTranslatef( m_element[i].x, m_element[i].y,0);
00221 
00222        glBegin( GL_QUADS );
00223        {
00224               glTexCoord2f( 0, 0 );
00225            glVertex2f( 0, 0 );
00226 
00227            glTexCoord2f( double(m_element[i].width) / m_element[i].size,
00228                        0 );
00229            glVertex2f( m_element[i].width, 0 );
00230 
00231            glTexCoord2f( 
00232                      double(m_element[i].width) / m_element[i].size,
00233                      double(m_element[i].height) / m_element[i].size );
00234            glVertex2f( m_element[i].width, m_element[i].height );
00235 
00236            glTexCoord2f( 
00237                      0,
00238                      double(m_element[i].height) / m_element[i].size );
00239            glVertex2f( 0, m_element[i].height );
00240        }
00241        glEnd();
00242     }
00243     glPopMatrix();
00244 }
00245 
00246 void
00247 HUD::time(const int i)
00248 {
00249     if(m_element[i].font){
00250               char string[BUFF_LEN];
00251               int minutes, seconds, hundredths;
00252                   
00253               getTimeComponents( gameMgr->time, minutes, seconds, hundredths );
00254               sprintf( string, m_element[i].string.c_str(), minutes, seconds, hundredths);
00255               
00256               pp::Font::utf8ToUnicode(m_element[i].u_string,string);
00257               int width = int(m_element[i].font->advance(m_element[i].u_string));
00258               
00259               fix_xy(m_element[i].x,m_element[i].y,m_element[i].height,width);
00260               m_element[i].font->draw(m_element[i].u_string, m_element[i].x, m_element[i].y);            
00261        
00262        }
00263 }
00264 
00265 void
00266 HUD::speed(const int i, const double speed)
00267 {
00268        if(m_element[i].font){
00269               char string[BUFF_LEN];
00270               sprintf( string, m_element[i].string.c_str(), speed );
00271               
00272               pp::Font::utf8ToUnicode(m_element[i].u_string,string);
00273               int width = int(m_element[i].font->advance(m_element[i].u_string));
00274               
00275               fix_xy(m_element[i].x,m_element[i].y,m_element[i].height,width);
00276               m_element[i].font->draw(m_element[i].u_string, m_element[i].x-(width/2), m_element[i].y);         
00277               
00278        }      
00279 }
00280 
00281 void
00282 HUD::bar(const int i, double percentage)
00283 {
00284        if(!m_element[i].texture) return;
00285        
00286        if(percentage>1)percentage=1;
00287        
00288        double temp_sin=sin(double(m_element[i].angle)/180.0*M_PI);
00289        double temp_cos=cos(double(m_element[i].angle)/180.0*M_PI);
00290        
00291     glBindTexture( GL_TEXTURE_2D, m_element[i].texture );
00292 
00293        fix_xy(m_element[i].x,m_element[i].y,int(m_element[i].height));
00294        
00295     glPushMatrix();
00296     {
00297        glTranslatef(m_element[i].x, m_element[i].y,0);
00298 
00299        glBegin( GL_QUADS );
00300        {
00301               glTexCoord2f(0,0);
00302            glVertex2f(0,0);
00303 
00304            glTexCoord2f(1,0);
00305            glVertex2f(temp_cos*m_element[i].width,temp_sin*m_element[i].width);
00306 
00307        glTexCoord2f(1,percentage);
00308        glVertex2f(temp_cos*m_element[i].width+temp_sin*m_element[i].height*percentage,
00309                      temp_sin*m_element[i].width-temp_cos*m_element[i].height*percentage);
00310 
00311        glTexCoord2f(0,percentage);
00312        glVertex2f(temp_sin*m_element[i].height*percentage, (-1)*temp_cos*m_element[i].height*percentage);
00313 
00314        }
00315        glEnd();
00316     }
00317     glPopMatrix();
00318        
00319 }
00320 
00321 //Sollte man bei Gelegenheit noch konfigurierbar machen
00322 #define ENERGY_GAUGE_BOTTOM 3.0
00323 #define ENERGY_GAUGE_CENTER_X 71.0
00324 #define ENERGY_GAUGE_CENTER_Y 55.0
00325 #define SPEEDBAR_OUTER_RADIUS ( ENERGY_GAUGE_CENTER_X )
00326 #define SPEEDBAR_BASE_ANGLE 225
00327 #define SPEEDBAR_MAX_ANGLE 45
00328 #define SPEEDBAR_GREEN_MAX_SPEED ( MAX_PADDLING_SPEED * M_PER_SEC_TO_KM_PER_H )
00329 #define SPEEDBAR_YELLOW_MAX_SPEED 100
00330 #define SPEEDBAR_RED_MAX_SPEED 160
00331 #define SPEEDBAR_GREEN_FRACTION 0.5
00332 #define SPEEDBAR_YELLOW_FRACTION 0.25
00333 #define SPEEDBAR_RED_FRACTION 0.25
00334 #define SPEED_UNITS_Y_OFFSET 4.0
00335 
00336 static GLfloat energy_background_color[] = { 0.2, 0.2, 0.2, 0.5 };
00337 static GLfloat energy_foreground_color[] = { 0.54, 0.59, 1.0, 1.0 };
00338 static GLfloat speedbar_background_color[] = { 0.2, 0.2, 0.2, 0.5 };
00339 static GLfloat white[] = { 1.0, 1.0, 1.0, 1.0 };
00340 
00341 void
00342 HUD::initGauge()
00343 {
00344     const char *binding;
00345        
00346        binding = "gauge_energy_mask";
00347     if ( !get_texture_binding( binding, &m_energymaskTex ) ) {
00348               print_warning( IMPORTANT_WARNING,
00349                      "Couldn't get texture for binding %s", binding );
00350     }
00351        
00352        binding = "gauge_speed_mask";
00353     if ( !get_texture_binding( binding, &m_speedmaskTex ) ) {
00354               print_warning( IMPORTANT_WARNING,
00355                      "Couldn't get texture for binding %s", binding );
00356     }
00357            
00358        binding = "gauge_outline";
00359     if ( !get_texture_binding( binding, &m_outlineTex ) ) {
00360               print_warning( IMPORTANT_WARNING,
00361                      "Couldn't get texture for binding %s", binding );
00362     }
00363 }
00364 
00365 
00366 void
00367 HUD::gauge(const int i, const double speed, const double energy)
00368 {
00369        GLfloat xplane[4] = { 1.0/m_element[i].size, 0.0, 0.0, 0.0 };
00370     GLfloat yplane[4] = { 0.0, 1.0/m_element[i].size, 0.0, 0.0 };
00371     double y;
00372     double speedbar_frac;
00373 
00374        //the gauge bar needs it's own mode
00375        //we reset the mode at the end of the function
00376     set_gl_options( GAUGE_BARS );
00377 
00378     glTexGenfv( GL_S, GL_OBJECT_PLANE, xplane );
00379     glTexGenfv( GL_T, GL_OBJECT_PLANE, yplane );
00380 
00381     glPushMatrix();
00382     {
00383        glTranslatef( getparam_x_resolution() - m_element[i].width,
00384                     0,
00385                     0 );
00386 
00387        glColor4fv( energy_background_color );
00388 
00389        glBindTexture( GL_TEXTURE_2D, m_energymaskTex );
00390 
00391        y = ENERGY_GAUGE_BOTTOM + energy * m_element[i].height;
00392 
00393        glBegin( GL_QUADS );
00394        {
00395            glVertex2f( 0.0, y );
00396            glVertex2f( m_element[i].size, y );
00397            glVertex2f( m_element[i].size, m_element[i].size );
00398            glVertex2f( 0.0, m_element[i].size );
00399        }
00400        glEnd();
00401 
00402        glColor4fv( energy_foreground_color );
00403 
00404        glBegin( GL_QUADS );
00405        {
00406            glVertex2f( 0.0, 0.0 );
00407            glVertex2f( m_element[i].size, 0.0 );
00408            glVertex2f( m_element[i].size, y );
00409            glVertex2f( 0.0, y );
00410        }
00411        glEnd();
00412 
00413        /* Calculate the fraction of the speed bar to fill */
00414        speedbar_frac = 0.0;
00415 
00416        if ( speed > SPEEDBAR_GREEN_MAX_SPEED ) {
00417            speedbar_frac = SPEEDBAR_GREEN_FRACTION;
00418            
00419            if ( speed > SPEEDBAR_YELLOW_MAX_SPEED ) {
00420               speedbar_frac += SPEEDBAR_YELLOW_FRACTION;
00421               
00422               if ( speed > SPEEDBAR_RED_MAX_SPEED ) {
00423                   speedbar_frac += SPEEDBAR_RED_FRACTION;
00424               } else {
00425                   speedbar_frac +=
00426                      ( speed - SPEEDBAR_YELLOW_MAX_SPEED ) /
00427                      ( SPEEDBAR_RED_MAX_SPEED - SPEEDBAR_YELLOW_MAX_SPEED ) *
00428                      SPEEDBAR_RED_FRACTION;
00429               }
00430 
00431            } else {
00432               speedbar_frac += 
00433                   ( speed - SPEEDBAR_GREEN_MAX_SPEED ) /
00434                   ( SPEEDBAR_YELLOW_MAX_SPEED - SPEEDBAR_GREEN_MAX_SPEED ) *
00435                   SPEEDBAR_YELLOW_FRACTION;
00436            }
00437            
00438        } else {
00439            speedbar_frac +=  speed/SPEEDBAR_GREEN_MAX_SPEED * 
00440               SPEEDBAR_GREEN_FRACTION;
00441        }
00442 
00443        glColor4fv( speedbar_background_color );
00444 
00445        glBindTexture( GL_TEXTURE_2D, m_speedmaskTex );
00446 
00447        draw_partial_tri_fan( 1.0 );
00448 
00449        glColor4fv( white );
00450 
00451        draw_partial_tri_fan( MIN( 1.0, speedbar_frac ) );
00452 
00453        glColor4fv( white );
00454 
00455        glBindTexture( GL_TEXTURE_2D, m_outlineTex );
00456 
00457        glBegin( GL_QUADS );
00458        {
00459            glVertex2f( 0.0, 0.0 );
00460            glVertex2f( m_element[i].size, 0.0 );
00461            glVertex2f( m_element[i].size, m_element[i].size );
00462            glVertex2f( 0.0, m_element[i].size );
00463        }
00464        glEnd();
00465        
00466     }
00467     glPopMatrix();
00468        
00469        //we reset this because all other elements need TEXFONT
00470        set_gl_options( TEXFONT );
00471 }
00472 
00473 #define CIRCLE_DIVISIONS 10
00474 
00475 void 
00476 HUD::draw_partial_tri_fan(const double fraction)
00477 {
00478     int divs;
00479     double angle, angle_incr, cur_angle;
00480     int i;
00481     bool trifan = false;
00482     pp::Vec2d pt;
00483 
00484     angle = SPEEDBAR_BASE_ANGLE + 
00485        ( SPEEDBAR_MAX_ANGLE - SPEEDBAR_BASE_ANGLE ) * fraction;
00486 
00487     divs = int(( SPEEDBAR_BASE_ANGLE - angle ) * CIRCLE_DIVISIONS / 360.0);
00488 
00489     cur_angle = SPEEDBAR_BASE_ANGLE;
00490 
00491     angle_incr = 360.0 / CIRCLE_DIVISIONS;
00492 
00493     for (i=0; i<divs; i++) {
00494        if ( !trifan ) {
00495            start_tri_fan();
00496            trifan = true;
00497        }
00498 
00499        cur_angle -= angle_incr;
00500 
00501        pt = calc_new_fan_pt( cur_angle );
00502 
00503        glVertex2f( pt.x, pt.y );
00504     }
00505 
00506     if ( cur_angle > angle + EPS ) {
00507        cur_angle = angle;
00508        if ( !trifan ) {
00509            start_tri_fan();
00510            trifan = true;
00511        }
00512 
00513        pt = calc_new_fan_pt( cur_angle );
00514 
00515        glVertex2f( pt.x, pt.y );
00516     }
00517 
00518     if ( trifan ) {
00519        glEnd();
00520        trifan = false;
00521     }
00522 }
00523 
00524 pp::Vec2d
00525 HUD::calc_new_fan_pt(const double angle )
00526 {
00527     pp::Vec2d pt;
00528     pt.x = ENERGY_GAUGE_CENTER_X + cos( ANGLES_TO_RADIANS( angle ) ) *
00529        SPEEDBAR_OUTER_RADIUS;
00530     pt.y = ENERGY_GAUGE_CENTER_Y + sin( ANGLES_TO_RADIANS( angle ) ) *
00531        SPEEDBAR_OUTER_RADIUS;
00532 
00533     return pt;
00534 }
00535 
00536 void
00537 HUD::start_tri_fan(void)
00538 {
00539     pp::Vec2d pt;
00540 
00541     glBegin( GL_TRIANGLE_FAN );
00542     glVertex2f( ENERGY_GAUGE_CENTER_X, 
00543               ENERGY_GAUGE_CENTER_Y );
00544 
00545     pt = calc_new_fan_pt( SPEEDBAR_BASE_ANGLE ); 
00546 
00547     glVertex2f( pt.x, pt.y );
00548 }
00549 
00550 void
00551 HUD::fix_xy(int &x, int &y, const int asc, const int width)
00552 {
00553        if(x<0){
00554               x=getparam_x_resolution()+x-width;
00555        }
00556        if(y<0){
00557               y=getparam_y_resolution()+y-asc;
00558        }
00559 }
00560 
00561 void
00562 HUD::coursePercentage(const int i)
00563 {
00564        if ( !getparam_display_course_percentage() ) {
00565               return;
00566     }
00567        
00568        if(m_element[i].font){
00569               char string[BUFF_LEN];
00570               sprintf( string, m_element[i].string.c_str(), players[0].getCoursePercentage() );
00571               
00572               pp::Font::utf8ToUnicode(m_element[i].u_string,string);
00573               int width = int(m_element[i].font->advance(m_element[i].u_string));
00574               
00575               fix_xy(m_element[i].x,m_element[i].y,m_element[i].height,width);
00576               m_element[i].font->draw(m_element[i].u_string, m_element[i].x, m_element[i].y);            
00577               
00578        }
00579 }
00580 
00581 void
00582 HUD::objectives_time(const int i, bool outline_font)
00583 {
00584     if(gameMgr->gametype!=GameMgr::PRACTICING ) {
00585         int minsLeft = -1;
00586         int secsLeft = -1;
00587         int centsLeft = -1;
00588         pp::Color green(0.0,1.0,0.0);
00589         pp::Color red(1.0,0.0,0.0);
00590         pp::Color black(0.0,0.0,0.0);
00591             
00592        if(m_element[i].font){
00593             if(      gameMgr->time <= gameMgr->getCurrentRace().time_req[gameMgr->difficulty]) {
00594                 m_element[i].font->setColor(green);
00595                 getTimeComponents( gameMgr->getCurrentRace().time_req[gameMgr->difficulty] - gameMgr->time, minsLeft, secsLeft, centsLeft );
00596             } else {
00597                 m_element[i].font->setColor(red);
00598                 minsLeft = 0;
00599                 secsLeft = 0;
00600                 centsLeft = 0;
00601             }
00602 
00603             if(outline_font) {
00604                 m_element[i].font->setColor(black);
00605             }
00606 
00607               char string[BUFF_LEN];
00608               sprintf( string, m_element[i].string.c_str(), minsLeft, secsLeft, centsLeft );
00609               
00610               pp::Font::utf8ToUnicode(m_element[i].u_string,string);
00611               int width = int(m_element[i].font->advance(m_element[i].u_string));
00612               
00613               fix_xy(m_element[i].x,m_element[i].y,m_element[i].height,width);
00614               m_element[i].font->draw(m_element[i].u_string, m_element[i].x-(width/2), m_element[i].y);         
00615               
00616        }
00617     }
00618 }
00619 
00620 void
00621 HUD::objectives_herring(const int i, bool outline_font)
00622 {
00623     if(gameMgr->gametype!=GameMgr::PRACTICING ) {
00624         pp::Color green(0.0,1.0,0.0);
00625         pp::Color red(1.0,0.0,0.0);
00626         pp::Color black(0.0,0.0,0.0);
00627         
00628         int req_herring = -1;
00629         
00630        if(m_element[i].font){
00631             if(players[0].herring >= gameMgr->getCurrentRace().herring_req[gameMgr->difficulty]) {
00632                 m_element[i].font->setColor(green);
00633                 req_herring = 0;
00634             } else {
00635                 m_element[i].font->setColor(red);
00636                 req_herring = gameMgr->getCurrentRace().herring_req[gameMgr->difficulty] - players[0].herring;
00637             }
00638             
00639             if(outline_font) {
00640                 m_element[i].font->setColor(black);
00641             }
00642         
00643               char string[BUFF_LEN];
00644               sprintf( string, m_element[i].string.c_str(), req_herring );
00645               
00646               pp::Font::utf8ToUnicode(m_element[i].u_string,string);
00647               int width = int(m_element[i].font->advance(m_element[i].u_string));
00648               
00649               fix_xy(m_element[i].x,m_element[i].y,m_element[i].height,width);
00650               m_element[i].font->draw(m_element[i].u_string, m_element[i].x-(width/2), m_element[i].y);         
00651               
00652        }      
00653     }
00654 }
00655 
00656 void 
00657 HUD::icon_time(const int i)
00658 {
00659        int m;
00660        m = i;
00661        
00662        if(gameMgr->time > gameMgr->getCurrentRace().time_req[gameMgr->difficulty] && gameMgr->gametype!=GameMgr::PRACTICING)
00663               m_element[m].texture = m_element[i].texture2;
00664        
00665        image(m);
00666 }
00667 
00668 void 
00669 HUD::icon_herring(const int i)
00670 {
00671        int m;
00672        m = i;
00673 
00674        if(players[0].herring >= gameMgr->getCurrentRace().herring_req[gameMgr->difficulty] && gameMgr->gametype!=GameMgr::PRACTICING)
00675               m_element[m].texture = m_element[i].texture2;
00676 
00677        image(m);
00678 }