Back to index

extremetuxracer  0.5beta
racing.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 "racing.h"
00023 
00024 #include "ppgltk/audio/audio.h"
00025 #include "ppgltk/alg/defs.h"
00026 
00027 #include "keyframe.h"
00028 #include "course_render.h"
00029 #include "gl_util.h"
00030 #include "fps.h"
00031 #include "loop.h"
00032 #include "render_util.h"
00033 #include "view.h"
00034 #include "model_hndl.h"
00035 #include "tux_shadow.h"
00036 #include "phys_sim.h"
00037 #include "part_sys.h"
00038 #include "screenshot.h"
00039 #include "fog.h"
00040 #include "viewfrustum.h"
00041 #include "track_marks.h"
00042 #include "hud.h"
00043 #include "joystick.h"
00044 #include "snow.h"
00045 #include "game_config.h"
00046 #include "winsys.h"
00047 
00048 #include "game_mgr.h"
00049 #include "bench.h"
00050 
00051 #include "ppgltk/ppgltk.h"
00052 
00053 
00054 /* Time constant for automatic steering centering (s) */
00055 #define TURN_DECAY_TIME_CONSTANT 0.5
00056 
00057 /* Maximum time over which jump can be charged */
00058 #define MAX_JUMP_AMT 1.0
00059 
00060 /* Time constant for automatic rolling centering (s) */
00061 #define ROLL_DECAY_TIME_CONSTANT 0.2
00062 
00063 #define JUMP_CHARGE_DECAY_TIME_CONSTANT 0.1
00064 
00065 /* If too high off the ground, tux flaps instead of jumping */
00066 #define JUMP_MAX_START_HEIGHT 0.30
00067 
00068 extern terrain_tex_t terrain_texture[NUM_TERRAIN_TYPES];
00069 extern unsigned int num_terrains;
00070 
00071 Racing::Racing()
00072 {
00073        m_rightTurn = false;
00074        m_leftTurn = false;
00075        m_trickModifier = false;
00076        m_paddling = false;
00077        m_charging = false;
00078        m_braking = false;
00079        
00080     // Initialize view
00081     if ( getparam_view_mode() < 0 || 
00082               getparam_view_mode() >= NUM_VIEW_MODES ) 
00083     {
00084               setparam_view_mode( ABOVE );
00085     }
00086     set_view_mode( players[0], (view_mode_t)getparam_view_mode() );
00087 
00088     // We need to reset controls here since callbacks won't have been
00089     //   called in paused mode. This results in duplication between this
00090     //   code and init_physical_simulation.  Oh well. 
00091 
00092     players[0].control.turn_fact = 0.0;
00093     players[0].control.turn_animation = 0.0;
00094     players[0].control.is_braking = false;
00095     players[0].control.is_paddling = false;
00096     players[0].control.jumping = false;
00097     players[0].control.jump_charging = false;
00098        players[0].max_speed = 0;
00099 
00100     // Set last_terrain to a value not used below
00101     m_lastTerrain = 0;
00102     
00103     if ( GameMode::prevmode != PAUSED ) {
00104               init_physical_simulation();
00105     }
00106 
00107     if(gameMgr->getCurrentRace().snowing) {
00108         int snowtype = gameMgr->getCurrentRace().snowtype;
00109         if(snowtype > -1) {
00110             SetSnowType(snowtype);
00111         }
00112         init_snow(players[0].pos);
00113     }
00114     
00115     if(gameMgr->getCurrentRace().windy) {
00116               int windtype = gameMgr->getCurrentRace().windtype;
00117         if(windtype > -1) {
00118             SetWindType(windtype);
00119         }
00120        }
00121     
00122     gameMgr->abortRace(false);
00123               
00124 if (gameMgr->gametype!=GameMgr::PRACTICING) {
00125        std::string mus = gameMgr->currentEvent->music;
00126        mus += "_racing";
00127        play_music( (char *)mus.c_str() );
00128 }
00129 else {
00130        play_music("racing");
00131 }
00132  
00133 }
00134 
00135 
00136 
00137 Racing::~Racing()
00138 {
00139        //todo: stop all sound which are specified by the used theme
00140        halt_sound( "flying_sound" );
00141     halt_sound( "rock_sound" );
00142     halt_sound( "ice_sound" );
00143     halt_sound( "snow_sound" );
00144     break_track_marks();
00145 }
00146 
00147 void
00148 Racing::loop(float timeStep)
00149 {
00150        int width, height;
00151     bool joy_left_turn = false;
00152     bool joy_right_turn = false;
00153     double joy_turn_fact = 0.0;
00154     bool joy_paddling = false;
00155     bool joy_braking = false;
00156     bool joy_tricks = false;
00157     bool joy_charging = false;
00158     bool airborne;
00159     pp::Vec3d dir;
00160     float speed;
00161     float terrain_weights[NUM_TERRAIN_TYPES];
00162     int new_terrain = 0;
00163     int slide_volume;
00164        unsigned int i;
00165 
00166        if (Benchmark::getMode() == Benchmark::AUTO){
00167               m_paddling = true;
00168        }      
00169        
00170     dir = players[0].vel;
00171     speed = dir.normalize();
00172        
00173        //set max_speed
00174        if (speed > players[0].max_speed) players[0].max_speed=int(speed);
00175 
00176        
00177     airborne = (bool) ( players[0].pos.y > ( find_y_coord(players[0].pos.x, 
00178                                                  players[0].pos.z) + 
00179                                      JUMP_MAX_START_HEIGHT ) );
00180 
00181     width = getparam_x_resolution();
00182     height = getparam_y_resolution();
00183 
00184     fpsCounter.update();
00185 
00186     update_audio();
00187 
00188     clear_rendering_context();
00189 
00190     fogPlane.setup();
00191 
00192     // Joystick
00193 
00194     if ( is_joystick_active() ) {
00195        float joy_x;
00196        float joy_y;
00197 
00198        update_joystick();
00199 
00200        joy_x = get_joystick_x_axis();
00201        joy_y = get_joystick_y_axis();
00202 
00203        if ( joy_x > 0.1 ) {
00204            joy_right_turn = true;
00205            joy_turn_fact = joy_x;
00206        } else if ( joy_x < -0.1 ) {
00207            joy_left_turn = true;
00208            joy_turn_fact = joy_x;
00209        }
00210 
00211        if ( getparam_joystick_brake_button() >= 0 ) {
00212            joy_braking = 
00213               is_joystick_button_down( getparam_joystick_brake_button() );
00214        } 
00215        if ( !joy_braking ) {
00216            joy_braking = (bool) ( joy_y > 0.5 );
00217        }
00218 
00219        if ( getparam_joystick_paddle_button() >= 0 ) {
00220            joy_paddling = 
00221               is_joystick_button_down( getparam_joystick_paddle_button() );
00222        }
00223        if ( !joy_paddling ) {
00224            joy_paddling = (bool) ( joy_y < -0.5 );
00225        }
00226 
00227        if ( getparam_joystick_jump_button() >= 0 ) {
00228            joy_charging = 
00229               is_joystick_button_down( getparam_joystick_jump_button() );
00230        }
00231 
00232        if ( getparam_joystick_trick_button() >= 0 ) {
00233            joy_tricks = 
00234               is_joystick_button_down( getparam_joystick_trick_button() );
00235        }
00236     }
00237 
00238     // Update braking 
00239     players[0].control.is_braking = (bool) ( m_braking || joy_braking );
00240 
00241     if ( airborne ) {
00242        new_terrain = (1<<4);
00243 
00244        // Tricks
00245        if ( m_trickModifier || joy_tricks ) {
00246            if ( m_leftTurn || joy_left_turn ) {
00247               players[0].control.barrel_roll_left = true;
00248            }
00249            if ( m_rightTurn || joy_right_turn ) {
00250               players[0].control.barrel_roll_right = true;
00251            }
00252            if ( m_paddling || joy_paddling ) {
00253               players[0].control.front_flip = true;
00254            }
00255            if ( players[0].control.is_braking ) {
00256               players[0].control.back_flip = true;
00257            }
00258        }
00259 
00260               for(i=0;i<num_terrains;i++){
00261                      if ( !terrain_texture[i].sound.empty() && terrain_texture[i].soundactive==true) {
00262                             halt_sound( terrain_texture[i].sound.c_str() );
00263                             terrain_texture[i].soundactive=false;
00264                      }
00265               }
00266               
00267     } else {
00268 
00269        get_surface_type(players[0].pos.x, players[0].pos.z, terrain_weights);
00270        
00271 
00272     //Play sliding sound
00273               
00274               slide_volume = int(MIN( (((pow(players[0].control.turn_fact, 2)*128)) +
00275                       (players[0].control.is_braking?128:0) +
00276                       (players[0].control.jumping?128:0) +
00277                       20) *
00278                      (speed/10), 128 ));
00279               
00280               for(i=0;i<num_terrains;i++){
00281                      if ( !terrain_texture[i].sound.empty() ) {
00282                             if (terrain_weights[i] > 0 ){
00283                                    set_sound_volume(terrain_texture[i].sound.c_str(), int(slide_volume * terrain_weights[i]));
00284                                    if (terrain_texture[i].soundactive==false){
00285                                           play_sound(terrain_texture[i].sound.c_str() , -1 );
00286                                           terrain_texture[i].soundactive=true;
00287                                    }
00288                             } else if (terrain_texture[i].soundactive==true){
00289                                    halt_sound( terrain_texture[i].sound.c_str() );
00290                                    terrain_texture[i].soundactive=false;
00291                             }
00292                      }
00293               }
00294               
00295                      
00296     }
00297 
00298     // Jumping
00299 
00300     calcJumpAmt( timeStep );
00301 
00302     if ( ( m_charging || joy_charging ) && 
00303         !players[0].control.jump_charging && !players[0].control.jumping ) 
00304     {
00305               players[0].control.jump_charging = true;
00306               m_chargeStartTime = gameMgr->time;
00307     }
00308 
00309     if ( ( !m_charging && !joy_charging ) && players[0].control.jump_charging ) {
00310               players[0].control.jump_charging = false;
00311               players[0].control.begin_jump = true;
00312     }
00313 
00314  
00315     // Turning 
00316 
00317     if ( ( m_leftTurn || joy_left_turn )  ^ (m_rightTurn || joy_right_turn ) ) {
00318        bool turning_left = (bool) ( m_leftTurn || joy_left_turn );
00319 
00320        if ( joy_left_turn || joy_right_turn ) {
00321            players[0].control.turn_fact = joy_turn_fact;
00322        } else {
00323            players[0].control.turn_fact = (turning_left?-1:1);
00324        }
00325 
00326        players[0].control.turn_animation += (turning_left?-1:1) *
00327            0.15 * timeStep / 0.05;
00328        players[0].control.turn_animation = 
00329            MIN(1.0, MAX(-1.0, players[0].control.turn_animation));
00330     } else {
00331        players[0].control.turn_fact = 0;
00332 
00333        // Decay turn animation
00334        if ( timeStep < ROLL_DECAY_TIME_CONSTANT ) {
00335            players[0].control.turn_animation *= 
00336               1.0 - timeStep/ROLL_DECAY_TIME_CONSTANT;
00337        } else {
00338            players[0].control.turn_animation = 0.0;
00339        }
00340     }
00341 
00342     
00343     
00344     //Paddling
00345     if ( ( m_paddling || joy_paddling ) && players[0].control.is_paddling == false ) {
00346               players[0].control.is_paddling = true;
00347               players[0].control.paddle_time = gameMgr->time;
00348     }
00349 
00350     
00351        //Play flying sound
00352 
00353     if (new_terrain & (1<<4)) {
00354               set_sound_volume("flying_sound", int(MIN(128, speed*2)));
00355               if (!(m_lastTerrain & (1<<4))) {
00356                  play_sound( "flying_sound", -1 );
00357               }
00358            } else {
00359               if (m_lastTerrain & (1<<4)) {
00360                   halt_sound( "flying_sound" );
00361               }
00362        }
00363 
00364        m_lastTerrain = new_terrain; 
00365 
00366        //Tricks
00367     if ( players[0].control.barrel_roll_left || players[0].control.barrel_roll_right ) {
00368        players[0].control.barrel_roll_factor += 
00369               ( players[0].control.barrel_roll_left ? -1 : 1 ) * 0.15 * timeStep / 0.05;
00370        if ( (players[0].control.barrel_roll_factor  > 1) ||
00371             (players[0].control.barrel_roll_factor  < -1) ) {
00372            players[0].control.barrel_roll_factor = 0;
00373            players[0].control.barrel_roll_left = players[0].control.barrel_roll_right = false;
00374        }
00375     }
00376     if ( players[0].control.front_flip || players[0].control.back_flip ) {
00377        players[0].control.flip_factor += 
00378               ( players[0].control.back_flip ? -1 : 1 ) * 0.15 * timeStep / 0.05;
00379        if ( (players[0].control.flip_factor  > 1) ||
00380             (players[0].control.flip_factor  < -1) ) {
00381            players[0].control.flip_factor = 0;
00382            players[0].control.front_flip = players[0].control.back_flip = false;
00383        }
00384     }
00385 
00386     update_player_pos( players[0], timeStep );
00387         
00388        //Track Marks
00389     add_track_mark( players[0] );
00390 
00391 
00392     update_view( players[0], timeStep );
00393 
00394     setup_view_frustum( players[0], NEAR_CLIP_DIST, 
00395                      getparam_forward_clip_distance() );
00396 
00397     draw_sky(players[0].view.pos);
00398 
00399     draw_fog_plane();
00400 
00401     set_course_clipping( true );
00402     set_course_eye_point( players[0].view.pos );
00403     setup_course_lighting();
00404     render_course();
00405        
00406        
00407     //Update wind
00408     if(gameMgr->getCurrentRace().windy) {
00409         update_wind();
00410     }
00411     
00412        //Draw snow
00413     if(gameMgr->getCurrentRace().snowing) {
00414         update_snow( timeStep, false, players[0].pos );
00415         draw_snow(players[0].view.pos);
00416     }
00417        
00418     draw_trees();
00419        
00420     if ( getparam_draw_particles() ) {
00421        update_particles( timeStep );
00422        draw_particles( players[0] );
00423     }
00424 
00425     ModelHndl->draw_tux();
00426     draw_tux_shadow();
00427 
00428     HUD1.draw(players[0]);
00429        
00430        
00431     reshape( width, height );
00432 
00433     winsys_swap_buffers();
00434 
00435     gameMgr->time += timeStep;
00436        if (airborne) gameMgr->airbornetime += timeStep;
00437               
00438        if(Benchmark::getMode() == Benchmark::PAUSED){
00439               set_game_mode(PAUSED);
00440        }
00441 }
00442 
00443 void
00444 Racing::calcJumpAmt( double time_step )
00445 {
00446     if ( players[0].control.jump_charging ) {
00447               players[0].control.jump_amt = MIN( 
00448            MAX_JUMP_AMT, gameMgr->time - m_chargeStartTime );
00449     } else if ( players[0].control.jumping ) {
00450               players[0].control.jump_amt *= 
00451            ( 1.0 - ( gameMgr->time - players[0].control.jump_start_time ) / 
00452              JUMP_FORCE_DURATION );
00453     } else {
00454               players[0].control.jump_amt = 0;
00455     }
00456 }
00457 
00458 
00459 bool
00460 Racing::keyboardEvent(SDLKey key, bool release)
00461 {
00462        if(key==getparam_turn_left_key()){
00463               m_leftTurn = (bool) !release;
00464               return true;
00465        }else if(key==getparam_turn_right_key()){
00466               m_rightTurn = (bool) !release;
00467               return true;
00468        }else if(key==getparam_paddle_key()){
00469               m_paddling = (bool) !release;
00470               return true;
00471        }else if(key==getparam_brake_key()){
00472               m_braking = (bool) !release;
00473               return true;
00474        }else if(key==getparam_trick_modifier_key()){
00475               m_trickModifier = (bool) !release;
00476               return true;
00477        }else if(key==getparam_jump_key()){
00478               m_charging = (bool) !release;
00479               return true;
00480        }else{
00481               return false;
00482        }
00483 }
00484 
00485 bool
00486 Racing::keyPressEvent(SDLKey key)
00487 {
00488        switch(key){
00489               case 'q':
00490                      gameMgr->abortRace();
00491                      set_game_mode( GAME_OVER );
00492                      return true;
00493               case SDLK_ESCAPE: 
00494                      set_game_mode( PAUSED );
00495                      return true;  
00496               case '1':
00497               set_view_mode( players[0], ABOVE );
00498               setparam_view_mode( ABOVE );
00499                      return true;
00500               case '2':
00501                      set_view_mode( players[0], FOLLOW );
00502                      setparam_view_mode( FOLLOW );
00503                      return true;
00504               case '3':
00505                      set_view_mode( players[0], BEHIND );
00506                      setparam_view_mode( BEHIND );
00507                      return true;  
00508               case 's':
00509               screenshot();
00510                      return true;
00511               case 'p':
00512                      set_game_mode( PAUSED );
00513                      return true;
00514               default:
00515                      if(key==getparam_reset_key()){
00516                             set_game_mode( RESET );
00517                             return true;
00518                      }
00519        }
00520               
00521        return false;
00522 }