- fixed problem with asyncron blinkig bonus block
[supertux.git] / src / gameloop.cpp
index 68d9869..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()
-{
-  current_ = this;
-  assert(0);
-}
-
-GameSession::GameSession(const std::string& filename)
+GameSession::GameSession(const std::string& subset_, int levelnb_, int mode)
+  : world(0), st_gl_mode(mode), levelnb(levelnb_), subset(subset_)
 {
-  init();
-
-  //assert(!"Don't call me");
   current_ = this;
-
-  world = new World;
-
-  fps_timer.init(true);
-  frame_timer.init(true);
-
-  world->load(filename);
+  restart_level();
 }
 
-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();
-
-  if(st_gl_mode == ST_GL_LOAD_GAME)
-    loadgame(levelnb);
+  start_timers(); 
 }
 
 GameSession::~GameSession()
@@ -130,23 +99,19 @@ GameSession::~GameSession()
 void
 GameSession::levelintro(void)
 {
-  Player& tux = *world->get_tux();
-
   char str[60];
   /* 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, 224, A_HMIDDLE, A_TOP, 1);
+  
   sprintf(str, "by %s", world->get_level()->author.c_str());
-  red_text->drawf(str, 0, 256, A_HMIDDLE, A_TOP, 1);
+  white_small_text->drawf(str, 0, 400, A_HMIDDLE, A_TOP, 1);
   
-  sprintf(str, "TUX x %d", tux.lives);
-  white_text->drawf(str, 0, 288, A_HMIDDLE, A_TOP, 1);
 
   flipscreen();
 
@@ -172,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;
@@ -193,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;
@@ -253,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;
@@ -267,7 +230,7 @@ GameSession::process_events()
                 break;
               case SDLK_l:
                 if(debug_mode)
-                  --tux.lives;
+                  --player_status.lives;
                 break;
               case SDLK_s:
                 if(debug_mode)
@@ -339,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!? */
-
-          if (tux.lives < 0)
-            {
+          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 
@@ -462,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;
@@ -493,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())
         {
@@ -509,7 +426,7 @@ GameSession::run()
         }
 
       /* Handle events: */
-      tux.input.old_fire = tux.input.fire;
+      tux->input.old_fire = tux->input.fire;
 
       process_events();
 
@@ -522,15 +439,9 @@ GameSession::run()
                 case 2:
                   st_pause_ticks_stop();
                   break;
-                case 3:
-                  update_load_save_game_menu(save_game_menu, false);
-                  break;
-                case 4:
-                  update_load_save_game_menu(load_game_menu, true);
-                  break;
-                case 7:
+                case 5:
                   st_pause_ticks_stop();
-                  done = true;
+                  exit_status = LEVEL_ABORT;
                   break;
                 }
             }
@@ -538,33 +449,26 @@ GameSession::run()
             {
               process_options_menu();
             }
-          else if(current_menu == save_game_menu )
-            {
-              process_save_game_menu();
-            }
           else if(current_menu == load_game_menu )
             {
               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
         {
@@ -610,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)
@@ -640,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: */
@@ -658,7 +559,6 @@ void bumpbrick(float x, float y)
 void
 GameSession::drawstatus()
 {
-  Player& tux = *world->get_tux();
   char str[60];
 
   sprintf(str, "%d", player_status.score);
@@ -696,7 +596,7 @@ GameSession::drawstatus()
       gold_text->draw(str, screen->h + 60, 40, 1);
     }
 
-  for(int i= 0; i < tux.lives; ++i)
+  for(int i= 0; i < player_status.lives; ++i)
     {
       tux_life->draw(565+(18*i),20);
     }
@@ -714,7 +614,7 @@ GameSession::drawendscreen()
   sprintf(str, "SCORE: %d", player_status.score);
   gold_text->drawf(str, 0, 224, A_HMIDDLE, A_TOP, 1);
 
-  sprintf(str, "DISTROS: %d", player_status.distros);
+  sprintf(str, "COINS: %d", player_status.distros);
   gold_text->drawf(str, 0, 256, A_HMIDDLE, A_TOP, 1);
 
   flipscreen();
@@ -744,129 +644,18 @@ GameSession::drawresultscreen(void)
   wait_for_event(event,2000,5000,true);
 }
 
-void
-GameSession::savegame(int)
-{
-#if 0
-  char savefile[1024];
-  FILE* fi;
-  unsigned int ui;
-
-  sprintf(savefile,"%s/slot%d.save",st_save_dir,slot);
-
-  fi = fopen(savefile, "wb");
-
-  if (fi == NULL)
-    {
-      fprintf(stderr, "Warning: I could not open the slot file ");
-    }
-  else
-    {
-      fputs(level_subset, fi);
-      fputs("\n", fi);
-      fwrite(&level,sizeof(int),1,fi);
-      fwrite(&score,sizeof(int),1,fi);
-      fwrite(&distros,sizeof(int),1,fi);
-      fwrite(&scroll_x,sizeof(float),1,fi);
-      //FIXME:fwrite(&tux,sizeof(Player),1,fi);
-      //FIXME:timer_fwrite(&tux.invincible_timer,fi);
-      //FIXME:timer_fwrite(&tux.skidding_timer,fi);
-      //FIXME:timer_fwrite(&tux.safe_timer,fi);
-      //FIXME:timer_fwrite(&tux.frame_timer,fi);
-      timer_fwrite(&time_left,fi);
-      ui = st_get_ticks();
-      fwrite(&ui,sizeof(int),1,fi);
-    }
-  fclose(fi);
-#endif 
-}
-
-void
-GameSession::loadgame(int)
-{
-#if 0
-  char savefile[1024];
-  char str[100];
-  FILE* fi;
-  unsigned int ui;
-
-  sprintf(savefile,"%s/slot%d.save",st_save_dir,slot);
-
-  fi = fopen(savefile, "rb");
-
-  if (fi == NULL)
-    {
-      fprintf(stderr, "Warning: I could not open the slot file ");
-
-    }
-  else
-    {
-      fgets(str, 100, fi);
-      strcpy(level_subset, str);
-      level_subset[strlen(level_subset)-1] = '\0';
-      fread(&level,sizeof(int),1,fi);
-
-      world->set_defaults();
-      world->get_level()->cleanup();
-      world->arrays_free();
-      world->get_level()->free_gfx();
-      world->get_level()->free_song();
-
-      if(world->get_level()->load(level_subset,level) != 0)
-        exit(1);
-
-      world->activate_bad_guys();
-      world->activate_particle_systems();
-      world->get_level()->load_gfx();
-      world->get_level()->load_song();
-
-      levelintro();
-      update_time = st_get_ticks();
-
-      fread(&score,   sizeof(int),1,fi);
-      fread(&distros, sizeof(int),1,fi);
-      fread(&scroll_x,sizeof(float),1,fi);
-      //FIXME:fread(&tux,     sizeof(Player), 1, fi);
-      //FIXME:timer_fread(&tux.invincible_timer,fi);
-      //FIXME:timer_fread(&tux.skidding_timer,fi);
-      //FIXME:timer_fread(&tux.safe_timer,fi);
-      //FIXME:timer_fread(&tux.frame_timer,fi);
-      timer_fread(&time_left,fi);
-      fread(&ui,sizeof(int),1,fi);
-      fclose(fi);
-    }
-#endif 
-}
-
 std::string slotinfo(int slot)
 {
-  FILE* fi;
+  char tmp[1024];
   char slotfile[1024];
-  char tmp[200];
-  char str[5];
-  int slot_level;
-  sprintf(slotfile,"%s/slot%d.save",st_save_dir,slot);
-
-  fi = fopen(slotfile, "rb");
+  sprintf(slotfile,"%s/slot%d.stsg",st_save_dir,slot);
 
-  sprintf(tmp,"Slot %d - ",slot);
-
-  if (fi == NULL)
-    {
-      strcat(tmp,"Free");
-    }
+  if (access(slotfile, F_OK) == 0)
+    sprintf(tmp,"Slot %d - Savegame",slot);
   else
-    {
-      fgets(str, 100, fi);
-      str[strlen(str)-1] = '\0';
-      strcat(tmp, str);
-      strcat(tmp, " / Level:");
-      fread(&slot_level,sizeof(int),1,fi);
-      sprintf(str,"%d",slot_level);
-      strcat(tmp,str);
-      fclose(fi);
-    }
+    sprintf(tmp,"Slot %d - Free",slot);
 
   return tmp;
 }
 
+