- fixed problem with asyncron blinkig bonus block
[supertux.git] / src / gameloop.cpp
index cb91373..5e86022 100644 (file)
@@ -10,6 +10,7 @@
   April 11, 2000 - March 15, 2004
 */
 
+#include <iostream>
 #include <assert.h>
 #include <stdio.h>
 #include <stdlib.h>
 
 GameSession* GameSession::current_ = 0;
 
-void
-GameSession::init()
-{
-  game_pause = false;
-}
-
-GameSession::GameSession()
+GameSession::GameSession(const std::string& subset_, int levelnb_, int mode)
+  : world(0), st_gl_mode(mode), levelnb(levelnb_), subset(subset_)
 {
   current_ = this;
-  assert(0);
+  restart_level();
 }
 
-GameSession::GameSession(const std::string& filename)
-{
-  init();
-
-  //assert(!"Don't call me");
-  current_ = this;
-
-  world = new World;
-
-  fps_timer.init(true);
-  frame_timer.init(true);
-
-  world->load(filename);
-}
-
-GameSession::GameSession(const std::string& subset_, int levelnb_, int mode)
-  : subset(subset_),
-    levelnb(levelnb_)
+void
+GameSession::restart_level()
 {
-  init();
-
-  current_ = this;
-
-  world = new World;
+  game_pause = false;
+  exit_status = NONE;
 
   fps_timer.init(true);
   frame_timer.init(true);
 
-  st_gl_mode = mode;
-  
-  /* Init the game: */
-  world->arrays_free();
-  world->set_defaults();
+  delete world;
 
   if (st_gl_mode == ST_GL_LOAD_LEVEL_FILE)
     {
-      if (world->load(subset))
-        exit(1);
+      world = new World(subset);
+    }
+  else if (st_gl_mode == ST_GL_DEMO_GAME)
+    {
+      world = new World(subset);
     }
   else
     {
-      if(world->load(subset, levelnb) != 0)
-        exit(1);
+      world = new World(subset, levelnb);
     }
+    
+  if (st_gl_mode != ST_GL_DEMO_GAME)
+    {
+      if(st_gl_mode != ST_GL_TEST)
+        load_hs();
 
-  world->get_level()->load_gfx();
-  
-  world->activate_bad_guys();
-  world->activate_particle_systems();
-  world->get_level()->load_song();
-
-  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();
+      if(st_gl_mode == ST_GL_PLAY || st_gl_mode == ST_GL_LOAD_LEVEL_FILE)
+        levelintro();
+    }
 
   time_left.init(true);
-  start_timers();
+  start_timers(); 
 }
 
 GameSession::~GameSession()
@@ -131,14 +103,11 @@ GameSession::levelintro(void)
   /* Level Intro: */
   clearscreen(0, 0, 0);
 
-  sprintf(str, "LEVEL %d", levelnb);
-  blue_text->drawf(str, 0, 200, A_HMIDDLE, A_TOP, 1);
-
   sprintf(str, "%s", world->get_level()->name.c_str());
-  gold_text->drawf(str, 0, 224, A_HMIDDLE, A_TOP, 1);
+  gold_text->drawf(str, 0, 200, A_HMIDDLE, A_TOP, 1);
 
   sprintf(str, "TUX x %d", player_status.lives);
-  white_text->drawf(str, 0, 256, A_HMIDDLE, A_TOP, 1);
+  white_text->drawf(str, 0, 224, A_HMIDDLE, A_TOP, 1);
   
   sprintf(str, "by %s", world->get_level()->author.c_str());
   white_small_text->drawf(str, 0, 400, A_HMIDDLE, A_TOP, 1);
@@ -168,14 +137,14 @@ GameSession::process_events()
   while (SDL_PollEvent(&event))
     {
       /* Check for menu-events, if the menu is shown */
-      if(show_menu)
-        current_menu->event(event);
+      current_menu->event(event);
 
       switch(event.type)
         {
         case SDL_QUIT:        /* Quit event - quit: */
-          quit = true;
+          st_abort("Received window close", "");
           break;
+
         case SDL_KEYDOWN:     /* A keypress! */
           {
             SDLKey key = event.key.keysym.sym;
@@ -189,8 +158,10 @@ GameSession::process_events()
                 if(!game_pause)
                   {
                     if(st_gl_mode == ST_GL_TEST)
-                      quit = true;
-                    else if(show_menu)
+                      {
+                        exit_status = LEVEL_ABORT;
+                      }
+                    else if(!show_menu)
                       {
                         Menu::set_current(game_menu);
                         show_menu = 0;
@@ -249,10 +220,6 @@ GameSession::process_events()
                 if(debug_mode)
                   player_status.distros += 50;
                 break;
-              case SDLK_SPACE:
-                if(debug_mode)
-                  player_status.next_level = 1;
-                break;
               case SDLK_DELETE:
                 if(debug_mode)
                   tux.got_coffee = 1;
@@ -335,100 +302,58 @@ GameSession::process_events()
     } /* while */
 }
 
-int
-GameSession::action(double frame_ratio)
+
+void
+GameSession::check_end_conditions()
 {
-  Player& tux = *world->get_tux();
+  Player* tux = world->get_tux();
 
-  if (tux.is_dead() || player_status.next_level)
+  /* End of level? */
+  if (tux->base.x >= World::current()->get_level()->endpos
+      && World::current()->get_level()->endpos != 0)
     {
-      /* Tux either died, or reached the end of a level! */
-      halt_music();
-      
-      if (player_status.next_level)
-        {
-          /* End of a level! */
-          levelnb++;
-          player_status.next_level = 0;
-          if(st_gl_mode != ST_GL_TEST)
-            {
-              drawresultscreen();
-            }
-          else
-            {
-              world->get_level()->free_gfx();
-              world->get_level()->cleanup();
-              world->get_level()->free_song();
-              world->arrays_free();
-
-              return(0);
-            }
-          tux.level_begin();
-        }
-      else
+      exit_status = LEVEL_FINISHED;
+    }
+  else
+    {
+      // Check End conditions
+      if (tux->is_dead())
         {
-          tux.is_dying();
-
-          /* No more lives!? */
-
+          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);
+                  // FIXME: highscore soving doesn't make sense in its
+                  // current form
+                  //if (player_status.score > hs_score)
+                  //save_hs(player_status.score);
                 }
-
-              world->get_level()->free_gfx();
-              world->get_level()->cleanup();
-              world->get_level()->free_song();
-              world->arrays_free();
-
-              return(0);
-            } /* if (lives < 0) */
-        }
-
-      /* Either way, (re-)load the (next) level... */
-      tux.level_begin();
-      world->set_defaults();
-      
-      world->get_level()->cleanup();
-
-      if (st_gl_mode == ST_GL_LOAD_LEVEL_FILE)
-        {
-          if(world->get_level()->load(subset) != 0)
-            return 0;
-        }
-      else
-        {
-          if(world->get_level()->load(subset, levelnb) != 0)
-            return 0;
+              
+              exit_status = GAME_OVER;
+            }
+          else
+            { // Still has lives, so reset Tux to the levelstart
+              restart_level();
+            }
         }
+    } 
+}
 
-      world->arrays_free();
-      world->activate_bad_guys();
-      world->activate_particle_systems();
-
-      world->get_level()->free_gfx();
-      world->get_level()->load_gfx();
-      world->get_level()->free_song();
-      world->get_level()->load_song();
-
-      if(st_gl_mode != ST_GL_TEST)
-        levelintro();
-      start_timers();
-      /* Play music: */
-      play_current_music();
+void
+GameSession::action(double frame_ratio)
+{
+  check_end_conditions();
+  
+  if (exit_status == NONE)
+    {
+      // Update Tux and the World
+      world->action(frame_ratio);
     }
-
-  tux.action(frame_ratio);
-
-  world->action(frame_ratio);
-
-  return -1;
 }
 
 void 
@@ -458,14 +383,13 @@ GameSession::draw()
 }
 
 
-int
+GameSession::ExitStatus
 GameSession::run()
 {
-  Player& tux = *world->get_tux();
+  Player* tux = world->get_tux();
   current_ = this;
   
   int  fps_cnt;
-  bool done;
 
   global_frame_counter = 0;
   game_pause = false;
@@ -489,14 +413,11 @@ GameSession::run()
 
   draw();
 
-  done = false;
-  quit = false;
-  while (!done && !quit)
+  float overlap = 0.0f;
+  while (exit_status == NONE)
     {
       /* Calculate the movement-factor */
       double frame_ratio = ((double)(update_time-last_update_time))/((double)FRAME_RATE);
-      if(frame_ratio > 1.5) /* Quick hack to correct the unprecise CPU clocks a little bit. */
-        frame_ratio = 1.5 + (frame_ratio - 1.5) * 0.85;
 
       if(!frame_timer.check())
         {
@@ -505,7 +426,7 @@ GameSession::run()
         }
 
       /* Handle events: */
-      tux.input.old_fire = tux.input.fire;
+      tux->input.old_fire = tux->input.fire;
 
       process_events();
 
@@ -518,16 +439,9 @@ GameSession::run()
                 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();
-                  done = true;
+                  exit_status = LEVEL_ABORT;
                   break;
                 }
             }
@@ -540,24 +454,21 @@ GameSession::run()
               process_load_game_menu();
             }
         }
-
-
-      /* Handle actions: */
-
+      
+      // Handle actions:
       if(!game_pause && !show_menu)
         {
-          /*float z = frame_ratio;
-            frame_ratio = 1;
-            while(z >= 1)
-            {*/
-          if (action(frame_ratio) == 0)
+          frame_ratio *= game_speed;
+          frame_ratio += overlap;
+          while (frame_ratio > 0)
             {
-              /* == 0: no more lives */
-              /* == -1: continues */
-              return 0;
+              action(1.0f);
+              frame_ratio -= 1.0f;
             }
-          /*  --z;
-                     }*/
+          overlap = frame_ratio;
+
+          if (exit_status != NONE)
+            return exit_status;
         }
       else
         {
@@ -603,15 +514,14 @@ GameSession::run()
         {
           /* are we low on time ? */
           if (time_left.get_left() < TIME_WARNING
-              && (get_current_music() != HURRYUP_MUSIC))     /* play the fast music */
+              && (get_current_music() != HURRYUP_MUSIC)) /* play the fast music */
             {
               set_current_music(HURRYUP_MUSIC);
               play_current_music();
             }
-
         }
-      else if(tux.dying == DYING_NOT)
-        tux.kill(KILL);
+      else if(tux->dying == DYING_NOT)
+        tux->kill(KILL);
 
       /* Calculate frames per second */
       if(show_fps)
@@ -633,9 +543,7 @@ GameSession::run()
   world->get_level()->cleanup();
   world->get_level()->free_song();
 
-  world->arrays_free();
-
-  return quit;
+  return exit_status;
 }
 
 /* Bounce a brick: */