Included supertux.h stuff into it.
[supertux.git] / src / gameloop.cpp
index e0cbe6a..834f98f 100644 (file)
 #include "collision.h"
 #include "tile.h"
 #include "particlesystem.h"
-
-/* extern variables */
-
-int game_started = false;
-
-/* Local variables: */
-static SDL_Event event;
-static SDLKey key;
-static char level_subset[100];
-static float fps_fps;
-static int st_gl_mode;
-static unsigned int last_update_time;
-static unsigned int update_time;
-static int pause_menu_frame;
-static int debug_fps;
+#include "resources.h"
 
 GameSession* GameSession::current_ = 0;
 
-/* Local function prototypes: */
-void levelintro(void);
-void loadshared(void);
-void unloadshared(void);
-void drawstatus(void);
-void drawendscreen(void);
-void drawresultscreen(void);
+void
+GameSession::init()
+{
+  game_pause = false;
+}
 
 GameSession::GameSession()
 {
@@ -76,76 +60,83 @@ GameSession::GameSession()
 
 GameSession::GameSession(const std::string& filename)
 {
+  init();
+
+  //assert(!"Don't call me");
   current_ = this;
 
-  world = &::world;
+  world = new World;
 
-  timer_init(&fps_timer, true);
-  timer_init(&frame_timer, true);
+  fps_timer.init(true);
+  frame_timer.init(true);
 
   world->load(filename);
 }
 
-GameSession::GameSession(const std::string& subset, int levelnb, int mode)
+GameSession::GameSession(const std::string& subset_, int levelnb_, int mode)
+  : subset(subset_),
+    levelnb(levelnb_)
 {
-  current_ = this;
+  init();
 
-  world = &::world;
+  current_ = this;
 
-  timer_init(&fps_timer, true);
-  timer_init(&frame_timer, true);
+  world = new World;
 
-  game_started = true;
+  fps_timer.init(true);
+  frame_timer.init(true);
 
   st_gl_mode = mode;
-  level = levelnb;
-
+  
   /* Init the game: */
   world->arrays_free();
-  set_defaults();
-
-  strcpy(level_subset, subset.c_str());
+  world->set_defaults();
 
   if (st_gl_mode == ST_GL_LOAD_LEVEL_FILE)
     {
-      if (world->load(level_subset))
+      if (world->load(subset))
         exit(1);
     }
   else
     {
-      if(world->load(level_subset, level) != 0)
+      if(world->load(subset, levelnb) != 0)
         exit(1);
     }
 
   world->get_level()->load_gfx();
-  loadshared();
-  activate_bad_guys(world->get_level());
+  
+  world->activate_bad_guys();
   world->activate_particle_systems();
   world->get_level()->load_song();
 
-  tux.init();
-
   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();
 
-  timer_init(&time_left,true);
+  time_left.init(true);
   start_timers();
 
   if(st_gl_mode == ST_GL_LOAD_GAME)
     loadgame(levelnb);
 }
 
+GameSession::~GameSession()
+{
+  delete world;
+}
+
 void
 GameSession::levelintro(void)
 {
+  Player& tux = *world->get_tux();
+
   char str[60];
   /* Level Intro: */
   clearscreen(0, 0, 0);
 
-  sprintf(str, "LEVEL %d", level);
+  sprintf(str, "LEVEL %d", levelnb);
   text_drawf(&blue_text, str, 0, 200, A_HMIDDLE, A_TOP, 1);
 
   sprintf(str, "%s", world->get_level()->name.c_str());
@@ -164,133 +155,130 @@ GameSession::levelintro(void)
 void
 GameSession::start_timers()
 {
-  timer_start(&time_left, world->get_level()->time_left*1000);
+  time_left.start(world->get_level()->time_left*1000);
   st_pause_ticks_init();
   update_time = st_get_ticks();
 }
 
-void activate_bad_guys(Level* plevel)
-{
-  for (std::vector<BadGuyData>::iterator i = plevel->badguy_data.begin();
-       i != plevel->badguy_data.end();
-       ++i)
-    {
-      world.add_bad_guy(i->x, i->y, i->kind);
-    }
-}
-
 void
 GameSession::process_events()
 {
+  Player& tux = *world->get_tux();
+
+  SDL_Event event;
   while (SDL_PollEvent(&event))
     {
       /* Check for menu-events, if the menu is shown */
       if(show_menu)
-        menu_event(event);
+        current_menu->event(event);
 
       switch(event.type)
         {
         case SDL_QUIT:        /* Quit event - quit: */
-          quit = 1;
+          quit = true;
           break;
         case SDL_KEYDOWN:     /* A keypress! */
-          key = event.key.keysym.sym;
-
-          if(tux.key_event(key,DOWN))
-            break;
-
-          switch(key)
-            {
-            case SDLK_ESCAPE:    /* Escape: Open/Close the menu: */
-              if(!game_pause)
-                {
-                  if(st_gl_mode == ST_GL_TEST)
-                    quit = 1;
-                  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();
-                    }
-                }
-              break;
-            default:
+          {
+            SDLKey key = event.key.keysym.sym;
+            
+            if(tux.key_event(key,DOWN))
               break;
-            }
+
+            switch(key)
+              {
+              case SDLK_ESCAPE:    /* Escape: Open/Close the menu: */
+                if(!game_pause)
+                  {
+                    if(st_gl_mode == ST_GL_TEST)
+                      quit = true;
+                    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();
+                      }
+                  }
+                break;
+              default:
+                break;
+              }
+          }
           break;
         case SDL_KEYUP:      /* A keyrelease! */
-          key = event.key.keysym.sym;
-
-          if(tux.key_event(key, UP))
-            break;
+          {
+            SDLKey key = event.key.keysym.sym;
 
-          switch(key)
-            {
-            case SDLK_p:
-              if(!show_menu)
-                {
-                  if(game_pause)
-                    {
-                      game_pause = 0;
-                      st_pause_ticks_stop();
-                    }
-                  else
-                    {
-                      game_pause = 1;
-                      st_pause_ticks_start();
-                    }
-                }
-              break;
-            case SDLK_TAB:
-              if(debug_mode)
-                {
-                  tux.size = !tux.size;
-                  if(tux.size == BIG)
-                    {
-                      tux.base.height = 64;
-                    }
-                  else
-                    tux.base.height = 32;
-                }
-              break;
-            case SDLK_END:
-              if(debug_mode)
-                distros += 50;
+            if(tux.key_event(key, UP))
               break;
-            case SDLK_SPACE:
-              if(debug_mode)
-                next_level = 1;
-              break;
-            case SDLK_DELETE:
-              if(debug_mode)
-                tux.got_coffee = 1;
-              break;
-            case SDLK_INSERT:
-              if(debug_mode)
-                timer_start(&tux.invincible_timer,TUX_INVINCIBLE_TIME);
-              break;
-            case SDLK_l:
-              if(debug_mode)
-                --tux.lives;
-              break;
-            case SDLK_s:
-              if(debug_mode)
-                score += 1000;
-            case SDLK_f:
-              if(debug_fps)
-                debug_fps = false;
-              else
-                debug_fps = true;
-              break;
-            default:
-              break;
-            }
+
+            switch(key)
+              {
+              case SDLK_p:
+                if(!show_menu)
+                  {
+                    if(game_pause)
+                      {
+                        game_pause = false;
+                        st_pause_ticks_stop();
+                      }
+                    else
+                      {
+                        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;
+                      }
+                    else
+                      tux.base.height = 32;
+                  }
+                break;
+              case SDLK_END:
+                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;
+                break;
+              case SDLK_INSERT:
+                if(debug_mode)
+                  tux.invincible_timer.start(TUX_INVINCIBLE_TIME);
+                break;
+              case SDLK_l:
+                if(debug_mode)
+                  --tux.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;
 
         case SDL_JOYAXISMOTION:
@@ -349,29 +337,31 @@ GameSession::process_events()
 }
 
 int
-GameSession::action()
+GameSession::action(double frame_ratio)
 {
-  if (tux.is_dead() || next_level)
+  Player& tux = *world->get_tux();
+
+  if (tux.is_dead() || player_status.next_level)
     {
       /* Tux either died, or reached the end of a level! */
       halt_music();
       
-      if (next_level)
+      if (player_status.next_level)
         {
           /* End of a level! */
-          level++;
-          next_level = 0;
+          levelnb++;
+          player_status.next_level = 0;
           if(st_gl_mode != ST_GL_TEST)
             {
               drawresultscreen();
             }
           else
             {
-              level_free_gfx();
+              world->get_level()->free_gfx();
               world->get_level()->cleanup();
-              level_free_song();
-              unloadshared();
+              world->get_level()->free_song();
               world->arrays_free();
+
               return(0);
             }
           tux.level_begin();
@@ -389,42 +379,45 @@ GameSession::action()
 
               if(st_gl_mode != ST_GL_TEST)
                 {
-                  if (score > hs_score)
-                    save_hs(score);
+                  if (player_status.score > hs_score)
+                    save_hs(player_status.score);
                 }
-              level_free_gfx();
+
+              world->get_level()->free_gfx();
               world->get_level()->cleanup();
-              level_free_song();
-              unloadshared();
+              world->get_level()->free_song();
               world->arrays_free();
+
               return(0);
             } /* if (lives < 0) */
         }
 
       /* Either way, (re-)load the (next) level... */
-
       tux.level_begin();
-      set_defaults();
+      world->set_defaults();
+      
       world->get_level()->cleanup();
 
       if (st_gl_mode == ST_GL_LOAD_LEVEL_FILE)
         {
-          if(world->get_level()->load(level_subset) != 0)
+          if(world->get_level()->load(subset) != 0)
             return 0;
         }
       else
         {
-          if(world->get_level()->load(level_subset,level) != 0)
+          if(world->get_level()->load(subset, levelnb) != 0)
             return 0;
         }
 
       world->arrays_free();
-      activate_bad_guys(world->get_level());
+      world->activate_bad_guys();
       world->activate_particle_systems();
-      level_free_gfx();
+
+      world->get_level()->free_gfx();
       world->get_level()->load_gfx();
-      level_free_song();
+      world->get_level()->free_song();
       world->get_level()->load_song();
+
       if(st_gl_mode != ST_GL_TEST)
         levelintro();
       start_timers();
@@ -432,19 +425,9 @@ GameSession::action()
       play_current_music();
     }
 
-  tux.action();
-
-  world->action();
-
-  /* update particle systems */
-  std::vector<ParticleSystem*>::iterator p;
-  for(p = world->particle_systems.begin(); p != world->particle_systems.end(); ++p)
-    {
-      (*p)->simulate(frame_ratio);
-    }
+  tux.action(frame_ratio);
 
-  /* Handle all possible collisions. */
-  collision_handler();
+  world->action(frame_ratio);
 
   return -1;
 }
@@ -452,10 +435,7 @@ GameSession::action()
 void 
 GameSession::draw()
 {
-
-  
   world->draw();
-
   drawstatus();
 
   if(game_pause)
@@ -470,12 +450,11 @@ GameSession::draw()
     }
 
   if(show_menu)
-  {
-    menu_process_current();
-    mouse_cursor->draw();
-  }
+    {
+      menu_process_current();
+      mouse_cursor->draw();
+    }
 
-  /* (Update it all!) */
   updatescreen();
 }
 
@@ -483,20 +462,18 @@ GameSession::draw()
 int
 GameSession::run()
 {
+  Player& tux = *world->get_tux();
   current_ = this;
   
   int  fps_cnt;
-  bool jump;
   bool done;
 
-  /* --- MAIN GAME LOOP!!! --- */
-  jump = false;
-  done = false;
-  quit = 0;
   global_frame_counter = 0;
-  game_pause = 0;
-  timer_init(&fps_timer,true);
-  timer_init(&frame_timer,true);
+  game_pause = false;
+
+  fps_timer.init(true);
+  frame_timer.init(true);
+
   last_update_time = st_get_ticks();
   fps_cnt = 0;
 
@@ -507,27 +484,28 @@ GameSession::run()
   /* Play music: */
   play_current_music();
 
-  while (SDL_PollEvent(&event))
-  {}
+  // Eat unneeded events
+  SDL_Event event;
+  while (SDL_PollEvent(&event)) {}
 
   draw();
-  do
-    {
-      jump = false;
 
+  done = false;
+  quit = false;
+  while (!done && !quit)
+    {
       /* Calculate the movement-factor */
-      frame_ratio = ((double)(update_time-last_update_time))/((double)FRAME_RATE);
+      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(!timer_check(&frame_timer))
+      if(!frame_timer.check())
         {
-          timer_start(&frame_timer,25);
+          frame_timer.start(25);
           ++global_frame_counter;
         }
 
       /* Handle events: */
-
       tux.input.old_fire = tux.input.fire;
 
       process_events();
@@ -576,7 +554,7 @@ GameSession::run()
             frame_ratio = 1;
             while(z >= 1)
             {*/
-          if (action() == 0)
+          if (action(frame_ratio) == 0)
             {
               /* == 0: no more lives */
               /* == -1: continues */
@@ -617,21 +595,18 @@ GameSession::run()
       /* 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 && !jump) {
+      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);*/
 
-
-
       /* Handle time: */
-
-      if (timer_check(&time_left))
+      if (time_left.check())
         {
           /* are we low on time ? */
-          if ((timer_get_left(&time_left) < TIME_WARNING)
+          if (time_left.get_left() < TIME_WARNING
               && (get_current_music() != HURRYUP_MUSIC))     /* play the fast music */
             {
               set_current_music(HURRYUP_MUSIC);
@@ -642,76 +617,48 @@ GameSession::run()
       else
         tux.kill(KILL);
 
-
       /* Calculate frames per second */
       if(show_fps)
         {
           ++fps_cnt;
-          fps_fps = (1000.0 / (float)timer_get_gone(&fps_timer)) * (float)fps_cnt;
+          fps_fps = (1000.0 / (float)fps_timer.get_gone()) * (float)fps_cnt;
 
-          if(!timer_check(&fps_timer))
+          if(!fps_timer.check())
             {
-              timer_start(&fps_timer,1000);
+              fps_timer.start(1000);
               fps_cnt = 0;
             }
         }
-
     }
-  while (!done && !quit);
 
   halt_music();
 
-  level_free_gfx();
+  world->get_level()->free_gfx();
   world->get_level()->cleanup();
-  level_free_song();
-  unloadshared();
-  world->arrays_free();
+  world->get_level()->free_song();
 
-  game_started = false;
+  world->arrays_free();
 
-  return(quit);
-}
-
-/* Draw a tile on the screen: */
-
-void drawshape(float x, float y, unsigned int c, Uint8 alpha)
-{
-  if (c != 0)
-    {
-      Tile* ptile = TileManager::instance()->get(c);
-      if(ptile)
-        {
-          if(ptile->images.size() > 1)
-            {
-              texture_draw(&ptile->images[( ((global_frame_counter*25) / ptile->anim_speed) % (ptile->images.size()))],x,y, alpha);
-            }
-          else if (ptile->images.size() == 1)
-            {
-              texture_draw(&ptile->images[0],x,y, alpha);
-            }
-          else
-            {
-              //printf("Tile not dravable %u\n", c);
-            }
-        }
-    }
+  return quit;
 }
 
 /* Bounce a brick: */
 void bumpbrick(float x, float y)
 {
-  world.add_bouncy_brick(((int)(x + 1) / 32) * 32,
+  World::current()->add_bouncy_brick(((int)(x + 1) / 32) * 32,
                          (int)(y / 32) * 32);
 
   play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER);
 }
 
 /* (Status): */
-void drawstatus(void)
+void
+GameSession::drawstatus()
 {
+  Player& tux = *world->get_tux();
   char str[60];
 
-  sprintf(str, "%d", score);
+  sprintf(str, "%d", player_status.score);
   text_draw(&white_text, "SCORE", 0, 0, 1);
   text_draw(&gold_text, str, 96, 0, 1);
 
@@ -726,14 +673,14 @@ void drawstatus(void)
       text_draw(&white_text,"Press ESC To Return",0,20,1);
     }
 
-  if (timer_get_left(&time_left) > TIME_WARNING || (global_frame_counter % 10) < 5)
+  if (time_left.get_left() > TIME_WARNING || (global_frame_counter % 10) < 5)
     {
-      sprintf(str, "%d", timer_get_left(&time_left) / 1000 );
+      sprintf(str, "%d", time_left.get_left() / 1000 );
       text_draw(&white_text, "TIME", 224, 0, 1);
       text_draw(&gold_text, str, 304, 0, 1);
     }
 
-  sprintf(str, "%d", distros);
+  sprintf(str, "%d", player_status.distros);
   text_draw(&white_text, "DISTROS", screen->h, 0, 1);
   text_draw(&gold_text, str, 608, 0, 1);
 
@@ -746,14 +693,14 @@ void drawstatus(void)
       text_draw(&gold_text, str, screen->h + 60, 40, 1);
     }
 
-  for(int i=0; i < tux.lives; ++i)
+  for(int i= 0; i < tux.lives; ++i)
     {
       texture_draw(&tux_life,565+(18*i),20);
     }
 }
 
-
-void drawendscreen(void)
+void
+GameSession::drawendscreen()
 {
   char str[80];
 
@@ -761,10 +708,10 @@ void drawendscreen(void)
 
   text_drawf(&blue_text, "GAMEOVER", 0, 200, A_HMIDDLE, A_TOP, 1);
 
-  sprintf(str, "SCORE: %d", score);
+  sprintf(str, "SCORE: %d", player_status.score);
   text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1);
 
-  sprintf(str, "DISTROS: %d", distros);
+  sprintf(str, "DISTROS: %d", player_status.distros);
   text_drawf(&gold_text, str, 0, 256, A_HMIDDLE, A_TOP, 1);
 
   flipscreen();
@@ -773,7 +720,8 @@ void drawendscreen(void)
   wait_for_event(event,2000,5000,true);
 }
 
-void drawresultscreen(void)
+void
+GameSession::drawresultscreen(void)
 {
   char str[80];
 
@@ -781,10 +729,10 @@ void drawresultscreen(void)
 
   text_drawf(&blue_text, "Result:", 0, 200, A_HMIDDLE, A_TOP, 1);
 
-  sprintf(str, "SCORE: %d", score);
+  sprintf(str, "SCORE: %d", player_status.score);
   text_drawf(&gold_text, str, 0, 224, A_HMIDDLE, A_TOP, 1);
 
-  sprintf(str, "DISTROS: %d", distros);
+  sprintf(str, "DISTROS: %d", player_status.distros);
   text_drawf(&gold_text, str, 0, 256, A_HMIDDLE, A_TOP, 1);
 
   flipscreen();
@@ -794,8 +742,9 @@ void drawresultscreen(void)
 }
 
 void
-GameSession::savegame(int slot)
+GameSession::savegame(int)
 {
+#if 0
   char savefile[1024];
   FILE* fi;
   unsigned int ui;
@@ -816,22 +765,23 @@ GameSession::savegame(int slot)
       fwrite(&score,sizeof(int),1,fi);
       fwrite(&distros,sizeof(int),1,fi);
       fwrite(&scroll_x,sizeof(float),1,fi);
-      fwrite(&tux,sizeof(Player),1,fi);
-      timer_fwrite(&tux.invincible_timer,fi);
-      timer_fwrite(&tux.skidding_timer,fi);
-      timer_fwrite(&tux.safe_timer,fi);
-      timer_fwrite(&tux.frame_timer,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 slot)
+GameSession::loadgame(int)
 {
+#if 0
   char savefile[1024];
   char str[100];
   FILE* fi;
@@ -853,33 +803,36 @@ GameSession::loadgame(int slot)
       level_subset[strlen(level_subset)-1] = '\0';
       fread(&level,sizeof(int),1,fi);
 
-      set_defaults();
+      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->arrays_free();
-      activate_bad_guys(world->get_level());
+
+      world->activate_bad_guys();
       world->activate_particle_systems();
-      level_free_gfx();
       world->get_level()->load_gfx();
-      level_free_song();
       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);
-      fread(&tux,     sizeof(Player), 1, fi);
-      timer_fread(&tux.invincible_timer,fi);
-      timer_fread(&tux.skidding_timer,fi);
-      timer_fread(&tux.safe_timer,fi);
-      timer_fread(&tux.frame_timer,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)