Time is not stopped during menu display in gameloop (fix).
[supertux.git] / src / gameloop.cpp
index 1f1131a..40a609b 100644 (file)
@@ -1,14 +1,23 @@
-/*
-  gameloop.c
-  
-  Super Tux - Game Loop!
-  
-  by Bill Kendrick & Tobias Glaesser
-  bill@newbreedsoftware.com
-  http://www.newbreedsoftware.com/supertux/
-  
-  April 11, 2000 - March 15, 2004
-*/
+//  $Id$
+// 
+//  SuperTux
+//  Copyright (C) 2000 Bill Kendrick <bill@newbreedsoftware.com>
+//  Copyright (C) 2004 Tobias Glaesser <tobi.web@gmx.de>
+//  Copyright (C) 2004 Ingo Ruhnke <grumbel@gmx.de>
+//
+//  This program 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 2
+//  of the License, or (at your option) any later version.
+//
+//  This program 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, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 #include <iostream>
 #include <assert.h>
@@ -63,6 +72,15 @@ GameSession::restart_level()
   fps_timer.init(true);
   frame_timer.init(true);
 
+  float old_x_pos = -1;
+
+  if (world)
+    { // Tux has lost a life, so we try to respawn him at the nearest reset point
+      old_x_pos = world->get_tux()->base.x;
+    }
+  
+  delete world;
+
   if (st_gl_mode == ST_GL_LOAD_LEVEL_FILE)
     {
       world = new World(subset);
@@ -75,12 +93,28 @@ GameSession::restart_level()
     {
       world = new World(subset, levelnb);
     }
+
+  // Set Tux to the nearest reset point
+  if (old_x_pos != -1)
+    {
+      ResetPoint best_reset_point = { -1, -1 };
+      for(std::vector<ResetPoint>::iterator i = get_level()->reset_points.begin();
+          i != get_level()->reset_points.end(); ++i)
+        {
+          if (i->x < old_x_pos && best_reset_point.x < i->x)
+            best_reset_point = *i;
+        }
+      
+      if (best_reset_point.x != -1)
+        {
+          world->get_tux()->base.x = best_reset_point.x;
+          world->get_tux()->base.y = best_reset_point.y;
+        }
+    }
+
     
   if (st_gl_mode != ST_GL_DEMO_GAME)
     {
-      if(st_gl_mode != ST_GL_TEST)
-        load_hs();
-
       if(st_gl_mode == ST_GL_PLAY || st_gl_mode == ST_GL_LOAD_LEVEL_FILE)
         levelintro();
     }
@@ -127,6 +161,19 @@ GameSession::start_timers()
 }
 
 void
+GameSession::on_escape_press()
+{
+  if(st_gl_mode == ST_GL_TEST)
+    {
+      exit_status = LEVEL_ABORT;
+    }
+  else if (!Menu::current())
+    {
+      Menu::set_current(game_menu);
+    }
+}
+
+void
 GameSession::process_events()
 {
   Player& tux = *world->get_tux();
@@ -135,168 +182,154 @@ GameSession::process_events()
   while (SDL_PollEvent(&event))
     {
       /* Check for menu-events, if the menu is shown */
-      current_menu->event(event);
-
-      switch(event.type)
+      if (Menu::current())
         {
-        case SDL_QUIT:        /* Quit event - quit: */
-          st_abort("Received window close", "");
-          break;
+          Menu::current()->event(event);
+          st_pause_ticks_start();
+        }
+      else
+        {
+          st_pause_ticks_stop();
 
-        case SDL_KEYDOWN:     /* A keypress! */
-          {
-            SDLKey key = event.key.keysym.sym;
-            
-            if(tux.key_event(key,DOWN))
+          switch(event.type)
+            {
+            case SDL_QUIT:        /* Quit event - quit: */
+              st_abort("Received window close", "");
               break;
 
-            switch(key)
+            case SDL_KEYDOWN:     /* A keypress! */
               {
-              case SDLK_ESCAPE:    /* Escape: Open/Close the menu: */
-                if(!game_pause)
+                SDLKey key = event.key.keysym.sym;
+            
+                if(tux.key_event(key,DOWN))
+                  break;
+
+                switch(key)
                   {
-                    if(st_gl_mode == ST_GL_TEST)
-                      {
-                        exit_status = LEVEL_ABORT;
-                      }
-                    else if(!show_menu)
-                      {
-                        Menu::set_current(game_menu);
-                        show_menu = 0;
-                        st_pause_ticks_stop();
-                      }
-                    else
-                      {
-                        Menu::set_current(game_menu);
-                        show_menu = 1;
-                        st_pause_ticks_start();
-                      }
+                  case SDLK_ESCAPE:    /* Escape: Open/Close the menu: */
+                    on_escape_press();
+                    break;
+                  default:
+                    break;
                   }
-                break;
-              default:
-                break;
               }
-          }
-          break;
-        case SDL_KEYUP:      /* A keyrelease! */
-          {
-            SDLKey key = event.key.keysym.sym;
-
-            if(tux.key_event(key, UP))
               break;
-
-            switch(key)
+            case SDL_KEYUP:      /* A keyrelease! */
               {
-              case SDLK_p:
-                if(!show_menu)
+                SDLKey key = event.key.keysym.sym;
+
+                if(tux.key_event(key, UP))
+                  break;
+
+                switch(key)
                   {
-                    if(game_pause)
+                  case SDLK_p:
+                    if(!Menu::current())
                       {
-                        game_pause = false;
-                        st_pause_ticks_stop();
+                        if(game_pause)
+                          {
+                            game_pause = false;
+                            st_pause_ticks_stop();
+                          }
+                        else
+                          {
+                            game_pause = true;
+                            st_pause_ticks_start();
+                          }
                       }
-                    else
+                    break;
+                  case SDLK_TAB:
+                    if(debug_mode)
                       {
-                        game_pause = true;
-                        st_pause_ticks_start();
-                      }
-                  }
-                break;
-              case SDLK_TAB:
-                if(debug_mode)
-                  {
-                    tux.size = !tux.size;
-                    if(tux.size == BIG)
-                      {
-                        tux.base.height = 64;
+                        tux.size = !tux.size;
+                        if(tux.size == BIG)
+                          {
+                            tux.base.height = 64;
+                          }
+                        else
+                          tux.base.height = 32;
                       }
+                    break;
+                  case SDLK_END:
+                    if(debug_mode)
+                      player_status.distros += 50;
+                    break;
+                  case SDLK_DELETE:
+                    if(debug_mode)
+                      tux.got_coffee = 1;
+                    break;
+                  case SDLK_INSERT:
+                    if(debug_mode)
+                      tux.invincible_timer.start(TUX_INVINCIBLE_TIME);
+                    break;
+                  case SDLK_l:
+                    if(debug_mode)
+                      --player_status.lives;
+                    break;
+                  case SDLK_s:
+                    if(debug_mode)
+                      player_status.score += 1000;
+                  case SDLK_f:
+                    if(debug_fps)
+                      debug_fps = false;
                     else
-                      tux.base.height = 32;
+                      debug_fps = true;
+                    break;
+                  default:
+                    break;
                   }
-                break;
-              case SDLK_END:
-                if(debug_mode)
-                  player_status.distros += 50;
-                break;
-              case SDLK_DELETE:
-                if(debug_mode)
-                  tux.got_coffee = 1;
-                break;
-              case SDLK_INSERT:
-                if(debug_mode)
-                  tux.invincible_timer.start(TUX_INVINCIBLE_TIME);
-                break;
-              case SDLK_l:
-                if(debug_mode)
-                  --player_status.lives;
-                break;
-              case SDLK_s:
-                if(debug_mode)
-                  player_status.score += 1000;
-              case SDLK_f:
-                if(debug_fps)
-                  debug_fps = false;
-                else
-                  debug_fps = true;
-                break;
-              default:
-                break;
               }
-          }
-          break;
+              break;
 
-        case SDL_JOYAXISMOTION:
-          switch(event.jaxis.axis)
-            {
-            case JOY_X:
-              if (event.jaxis.value < -JOYSTICK_DEAD_ZONE)
-                {
-                  tux.input.left  = DOWN;
-                  tux.input.right = UP;
-                }
-              else if (event.jaxis.value > JOYSTICK_DEAD_ZONE)
+            case SDL_JOYAXISMOTION:
+              if (event.jaxis.axis == joystick_keymap.x_axis)
                 {
-                  tux.input.left  = UP;
-                  tux.input.right = DOWN;
+                  if (event.jaxis.value < -joystick_keymap.dead_zone)
+                    {
+                      tux.input.left  = DOWN;
+                      tux.input.right = UP;
+                    }
+                  else if (event.jaxis.value > joystick_keymap.dead_zone)
+                    {
+                      tux.input.left  = UP;
+                      tux.input.right = DOWN;
+                    }
+                  else
+                    {
+                      tux.input.left  = DOWN;
+                      tux.input.right = DOWN;
+                    }
                 }
-              else
+              else if (event.jaxis.axis == joystick_keymap.y_axis)
                 {
-                  tux.input.left  = DOWN;
-                  tux.input.right = DOWN;
+                  if (event.jaxis.value > joystick_keymap.dead_zone)
+                    tux.input.down = DOWN;
+                  else if (event.jaxis.value < -joystick_keymap.dead_zone)
+                    tux.input.down = UP;
+                  else
+                    tux.input.down = UP;
                 }
               break;
-            case JOY_Y:
-              if (event.jaxis.value > JOYSTICK_DEAD_ZONE)
-                tux.input.down = DOWN;
-              else if (event.jaxis.value < -JOYSTICK_DEAD_ZONE)
-                tux.input.down = UP;
-              else
-                tux.input.down = UP;
-              
-             break;
-            default:
+            
+            case SDL_JOYBUTTONDOWN:
+              if (event.jbutton.button == joystick_keymap.a_button)
+                tux.input.up = DOWN;
+              else if (event.jbutton.button == joystick_keymap.b_button)
+                tux.input.fire = DOWN;
+              else if (event.jbutton.button == joystick_keymap.start_button)
+                on_escape_press();
+              break;
+            case SDL_JOYBUTTONUP:
+              if (event.jbutton.button == joystick_keymap.a_button)
+                tux.input.up = UP;
+              else if (event.jbutton.button == joystick_keymap.b_button)
+                tux.input.fire = UP;
               break;
-            }
-          break;
-        case SDL_JOYBUTTONDOWN:
-          if (event.jbutton.button == JOY_A)
-            tux.input.up = DOWN;
-          else if (event.jbutton.button == JOY_B)
-            tux.input.fire = DOWN;
-          break;
-        case SDL_JOYBUTTONUP:
-          if (event.jbutton.button == JOY_A)
-            tux.input.up = UP;
-          else if (event.jbutton.button == JOY_B)
-            tux.input.fire = UP;
-           
-          break;
-
-        default:
-          break;
-
-        }  /* switch */
 
+            default:
+              break;
+            }  /* switch */
+        }
     } /* while */
 }
 
@@ -317,17 +350,12 @@ GameSession::check_end_conditions()
       // Check End conditions
       if (tux->is_dead())
         {
-          
+          player_status.lives -= 1;             
+    
           if (player_status.lives < 0)
             { // No more lives!?
               if(st_gl_mode != ST_GL_TEST)
                 drawendscreen();
-          
-              if(st_gl_mode != ST_GL_TEST)
-                {
-                  if (player_status.score > hs_score)
-                    save_hs(player_status.score);
-                }
               
               exit_status = GAME_OVER;
             }
@@ -368,9 +396,9 @@ GameSession::draw()
       blue_text->drawf("PAUSE - Press 'P' To Play", 0, 230, A_HMIDDLE, A_TOP, 1);
     }
 
-  if(show_menu)
+  if(Menu::current())
     {
-      menu_process_current();
+      Menu::current()->draw();
       mouse_cursor->draw();
     }
 
@@ -381,6 +409,7 @@ GameSession::draw()
 GameSession::ExitStatus
 GameSession::run()
 {
+  Menu::set_current(0);
   Player* tux = world->get_tux();
   current_ = this;
   
@@ -424,41 +453,37 @@ GameSession::run()
       tux->input.old_fire = tux->input.fire;
 
       process_events();
-
-      if(show_menu)
+      
+      Menu* menu = Menu::current();
+      if(menu)
         {
-          if(current_menu == game_menu)
+          menu->action();
+
+          if(menu == game_menu)
             {
               switch (game_menu->check())
                 {
                 case 2:
                   st_pause_ticks_stop();
                   break;
-                case 3:
-                  // FIXME:
-                  //update_load_save_game_menu(save_game_menu);
-                  break;
-                case 4:
-                  update_load_save_game_menu(load_game_menu);
-                  break;
-                case 7:
+                case 5:
                   st_pause_ticks_stop();
                   exit_status = LEVEL_ABORT;
                   break;
                 }
             }
-          else if(current_menu == options_menu)
+          else if(menu == options_menu)
             {
               process_options_menu();
             }
-          else if(current_menu == load_game_menu )
+          else if(menu == load_game_menu )
             {
               process_load_game_menu();
             }
         }
       
       // Handle actions:
-      if(!game_pause && !show_menu)
+      if(!game_pause && !Menu::current())
         {
           frame_ratio *= game_speed;
           frame_ratio += overlap;
@@ -492,7 +517,7 @@ GameSession::run()
       draw();
 
       /* Time stops in pause mode */
-      if(game_pause || show_menu )
+      if(game_pause || Menu::current())
         {
           continue;
         }
@@ -567,13 +592,7 @@ GameSession::drawstatus()
   white_text->draw("SCORE", 0, 0, 1);
   gold_text->draw(str, 96, 0, 1);
 
-  if(st_gl_mode != ST_GL_TEST)
-    {
-      sprintf(str, "%d", hs_score);
-      white_text->draw("HIGH", 0, 20, 1);
-      gold_text->draw(str, 96, 20, 1);
-    }
-  else
+  if(st_gl_mode == ST_GL_TEST)
     {
       white_text->draw("Press ESC To Return",0,20,1);
     }