Limitated the number of bullets to be shot at the same time.
[supertux.git] / src / gameloop.cpp
index 02b717b..229e8fd 100644 (file)
@@ -60,14 +60,16 @@ GameSession::GameSession(const std::string& subset_, int levelnb_, int mode)
   : world(0), st_gl_mode(mode), levelnb(levelnb_), subset(subset_)
 {
   current_ = this;
+  end_sequenze = false;
   restart_level();
 }
 
 void
 GameSession::restart_level()
 {
-  game_pause = false;
-  exit_status = NONE;
+  game_pause   = false;
+  exit_status  = NONE;
+  end_sequenze = false;
 
   fps_timer.init(true);
   frame_timer.init(true);
@@ -170,165 +172,185 @@ GameSession::on_escape_press()
   else if (!Menu::current())
     {
       Menu::set_current(game_menu);
-      st_pause_ticks_stop();
     }
 }
 
 void
 GameSession::process_events()
 {
-  Player& tux = *world->get_tux();
-
-  SDL_Event event;
-  while (SDL_PollEvent(&event))
+  if (end_sequenze)
     {
-      /* Check for menu-events, if the menu is shown */
-      if (Menu::current())
-        {
-          Menu::current()->event(event);
-        }
+      Player& tux = *world->get_tux();
+          
+      tux.input.left  = UP;
+      tux.input.right = DOWN; 
+      tux.input.down  = UP; 
+
+      if (int(last_x_pos) == int(tux.base.x))
+        tux.input.up    = DOWN; 
       else
+        tux.input.up    = UP; 
+
+      last_x_pos = tux.base.x;
+    }
+  else
+    {
+      SDL_Event event;
+      while (SDL_PollEvent(&event))
         {
-          switch(event.type)
+          /* Check for menu-events, if the menu is shown */
+          if (Menu::current())
             {
-            case SDL_QUIT:        /* Quit event - quit: */
-              st_abort("Received window close", "");
-              break;
+              Menu::current()->event(event);
+              st_pause_ticks_start();
+            }
+          else
+            {
+              Player& tux = *world->get_tux();
+  
+              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: */
-                    on_escape_press();
-                    break;
-                  default:
-                    break;
-                  }
-              }
-              break;
-            case SDL_KEYUP:      /* A keyrelease! */
-              {
-                SDLKey key = event.key.keysym.sym;
+                    SDLKey key = event.key.keysym.sym;
+            
+                    if(tux.key_event(key,DOWN))
+                      break;
 
-                if(tux.key_event(key, UP))
+                    switch(key)
+                      {
+                      case SDLK_ESCAPE:    /* Escape: Open/Close the menu: */
+                        on_escape_press();
+                        break;
+                      default:
+                        break;
+                      }
+                  }
                   break;
-
-                switch(key)
+                case SDL_KEYUP:      /* A keyrelease! */
                   {
-                  case SDLK_p:
-                    if(!Menu::current())
+                    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:
-              if (event.jaxis.axis == joystick_keymap.x_axis)
-                {
-                  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)
+                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;
                     }
-                }
-              else if (event.jaxis.axis == joystick_keymap.y_axis)
-                {
-                  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;
+                  break;
             
-            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;
+                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;
 
-            default:
-              break;
-            }  /* switch */
-        }
-    } /* while */
+                default:
+                  break;
+                }  /* switch */
+            }
+        } /* while */
+    }
 }
 
 
@@ -338,11 +360,16 @@ GameSession::check_end_conditions()
   Player* tux = world->get_tux();
 
   /* End of level? */
-  if (tux->base.x >= World::current()->get_level()->endpos
-      && World::current()->get_level()->endpos != 0)
+  if (tux->base.x >= World::current()->get_level()->endpos + 320)
     {
       exit_status = LEVEL_FINISHED;
     }
+  else if (tux->base.x >= World::current()->get_level()->endpos && !end_sequenze)
+    {
+      end_sequenze = true;
+      last_x_pos = -1;
+      halt_music();
+    }
   else
     {
       // Check End conditions
@@ -403,6 +430,37 @@ GameSession::draw()
   updatescreen();
 }
 
+void
+GameSession::process_menu()
+{
+  Menu* menu = Menu::current();
+  if(menu)
+    {
+      menu->action();
+
+      if(menu == game_menu)
+        {
+          switch (game_menu->check())
+            {
+            case 2:
+              st_pause_ticks_stop();
+              break;
+            case 5:
+              st_pause_ticks_stop();
+              exit_status = LEVEL_ABORT;
+              break;
+            }
+        }
+      else if(menu == options_menu)
+        {
+          process_options_menu();
+        }
+      else if(menu == load_game_menu )
+        {
+          process_load_game_menu();
+        }
+    }
+}
 
 GameSession::ExitStatus
 GameSession::run()
@@ -451,49 +509,25 @@ GameSession::run()
       tux->input.old_fire = tux->input.fire;
 
       process_events();
-      
-      Menu* menu = Menu::current();
-      if(menu)
-        {
-          menu->action();
+      process_menu();
 
-          if(menu == game_menu)
-            {
-              switch (game_menu->check())
-                {
-                case 2:
-                  st_pause_ticks_stop();
-                  break;
-                case 5:
-                  st_pause_ticks_stop();
-                  exit_status = LEVEL_ABORT;
-                  break;
-                }
-            }
-          else if(menu == options_menu)
-            {
-              process_options_menu();
-            }
-          else if(menu == load_game_menu )
-            {
-              process_load_game_menu();
-            }
-        }
-      
-      // Handle actions:
+      // Update the world state and all objects in the world
+      // Do that with a constante time-delta so that the game will run
+      // determistic and not different on different machines
       if(!game_pause && !Menu::current())
         {
           frame_ratio *= game_speed;
           frame_ratio += overlap;
           while (frame_ratio > 0)
             {
-              action(1.0f);
+              // Update the world
+              if (end_sequenze)
+                action(.5f);
+              else
+                action(1.0f);
               frame_ratio -= 1.0f;
             }
           overlap = frame_ratio;
-
-          if (exit_status != NONE)
-            return exit_status;
         }
       else
         {
@@ -501,17 +535,6 @@ GameSession::run()
           SDL_Delay(50);
         }
 
-      if(debug_mode && debug_fps)
-        SDL_Delay(60);
-
-      /*Draw the current scene to the screen */
-      /*If the machine running the game is too slow
-        skip the drawing of the frame (so the calculations are more precise and
-        the FPS aren't affected).*/
-      /*if( ! fps_fps < 50.0 )
-        game_draw();
-        else
-        jump = true;*/ /*FIXME: Implement this tweak right.*/
       draw();
 
       /* Time stops in pause mode */
@@ -522,17 +545,16 @@ GameSession::run()
 
       /* Set the time of the last update and the time of the current update */
       last_update_time = update_time;
-      update_time = st_get_ticks();
+      update_time      = st_get_ticks();
 
       /* Pause till next frame, if the machine running the game is too fast: */
       /* FIXME: Works great for in OpenGl mode, where the CPU doesn't have to do that much. But
          the results in SDL mode aren't perfect (thought the 100 FPS are reached), even on an AMD2500+. */
-      if(last_update_time >= update_time - 12) {
-        SDL_Delay(10);
-        update_time = st_get_ticks();
-      }
-      /*if((update_time - last_update_time) < 10)
-        SDL_Delay((11 - (update_time - last_update_time))/2);*/
+      if(last_update_time >= update_time - 12) 
+        {
+          SDL_Delay(10);
+          update_time = st_get_ticks();
+        }
 
       /* Handle time: */
       if (time_left.check())
@@ -546,7 +568,9 @@ GameSession::run()
             }
         }
       else if(tux->dying == DYING_NOT)
-        tux->kill(KILL);
+        {
+          tux->kill(KILL);
+        }
 
       /* Calculate frames per second */
       if(show_fps)
@@ -561,7 +585,7 @@ GameSession::run()
             }
         }
     }
-
+  
   halt_music();
 
   world->get_level()->free_gfx();