No more count-to-infinity for the coins display
[supertux.git] / src / title.cpp
index 94ccc5a..08259e8 100644 (file)
@@ -1,8 +1,8 @@
 //  $Id$
 //  $Id$
-// 
+//
 //  SuperTux
 //  SuperTux
-//  Copyright (C) 2000 Bill Kendrick <bill@newbreedsoftware.com>
 //  Copyright (C) 2004 Tobias Glaesser <tobi.web@gmx.de>
 //  Copyright (C) 2004 Tobias Glaesser <tobi.web@gmx.de>
+//  Copyright (C) 2006 Matthias Braun <matze@braunis.de>
 //
 //  This program is free software; you can redistribute it and/or
 //  modify it under the terms of the GNU General Public License
 //
 //  This program is free software; you can redistribute it and/or
 //  modify it under the terms of the GNU General Public License
@@ -13,7 +13,7 @@
 //  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.
 //  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
 //  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
@@ -34,7 +34,8 @@
 #include <physfs.h>
 
 #include "title.hpp"
 #include <physfs.h>
 
 #include "title.hpp"
-#include "video/screen.hpp"
+#include "mainloop.hpp"
+#include "video/drawing_context.hpp"
 #include "video/surface.hpp"
 #include "audio/sound_manager.hpp"
 #include "gui/menu.hpp"
 #include "video/surface.hpp"
 #include "audio/sound_manager.hpp"
 #include "gui/menu.hpp"
@@ -42,9 +43,9 @@
 #include "lisp/lisp.hpp"
 #include "lisp/parser.hpp"
 #include "level.hpp"
 #include "lisp/lisp.hpp"
 #include "lisp/parser.hpp"
 #include "level.hpp"
-#include "level_subset.hpp"
+#include "world.hpp"
 #include "game_session.hpp"
 #include "game_session.hpp"
-#include "worldmap.hpp"
+#include "worldmap/worldmap.hpp"
 #include "player_status.hpp"
 #include "tile.hpp"
 #include "sector.hpp"
 #include "player_status.hpp"
 #include "tile.hpp"
 #include "sector.hpp"
 #include "object/player.hpp"
 #include "resources.hpp"
 #include "gettext.hpp"
 #include "object/player.hpp"
 #include "resources.hpp"
 #include "gettext.hpp"
-#include "misc.hpp"
 #include "textscroller.hpp"
 #include "textscroller.hpp"
+#include "fadeout.hpp"
 #include "file_system.hpp"
 #include "control/joystickkeyboardcontroller.hpp"
 #include "control/codecontroller.hpp"
 #include "main.hpp"
 #include "file_system.hpp"
 #include "control/joystickkeyboardcontroller.hpp"
 #include "control/codecontroller.hpp"
 #include "main.hpp"
-#include "exceptions.hpp"
-
-static Surface* bkg_title;
-static Surface* logo;
-//static Surface* img_choose_subset;
-
-static bool walking;
-static Timer random_timer;
-
-static int frame;
-
-static GameSession* titlesession;
-static CodeController* controller;
-
-static std::vector<LevelSubset*> contrib_subsets;
-static LevelSubset* current_contrib_subset = 0;
-static int current_subset = -1;
-
-/* If the demo was stopped - because game started, level
-   editor was excuted, etc - call this when you get back
-   to the title code.
- */
-void resume_demo()
+#include "log.hpp"
+#include "options_menu.hpp"
+#include "console.hpp"
+#include "random_generator.hpp"
+
+enum MainMenuIDs {
+  MNID_STARTGAME,
+  MNID_LEVELS_CONTRIB,
+  MNID_OPTIONMENU,
+  MNID_LEVELEDITOR,
+  MNID_CREDITS,
+  MNID_QUITMAINMENU
+};
+
+void
+TitleScreen::update_load_game_menu()
 {
 {
-  player_status->reset();
-  titlesession->get_current_sector()->activate("main");
-  titlesession->set_current();
-
-  //frame_rate.update();
-}
+  load_game_menu.reset(new Menu());
 
 
-void update_load_save_game_menu(Menu* menu)
-{
-  printf("update loadsavemenu.\n");
-  for(int i = 1; i < 6; ++i) {
-    MenuItem& item = menu->get_item_by_id(i);
-    item.kind = MN_ACTION;
-    item.change_text(slotinfo(i));
+  load_game_menu->add_label(_("Start Game"));
+  load_game_menu->add_hl();
+  for(int i = 1; i <= 5; ++i) {
+    load_game_menu->add_entry(i, get_slotinfo(i));
   }
   }
+  load_game_menu->add_hl();
+  load_game_menu->add_back(_("Back"));
 }
 
 }
 
-void free_contrib_menu()
+void
+TitleScreen::free_contrib_menu()
 {
 {
-  for(std::vector<LevelSubset*>::iterator i = contrib_subsets.begin();
-      i != contrib_subsets.end(); ++i)
+  for(std::vector<World*>::iterator i = contrib_worlds.begin();
+      i != contrib_worlds.end(); ++i)
     delete *i;
 
     delete *i;
 
-  contrib_subsets.clear();
-  contrib_menu->clear();
-  current_contrib_subset = 0;
-  current_subset = -1;
+  contrib_worlds.clear();
 }
 
 }
 
-void generate_contrib_menu()
+void
+TitleScreen::generate_contrib_menu()
 {
   /** Generating contrib levels list by making use of Level Subset  */
 {
   /** Generating contrib levels list by making use of Level Subset  */
-  std::vector<std::string> level_subsets; 
+  std::vector<std::string> level_worlds;
   char** files = PHYSFS_enumerateFiles("levels/");
   for(const char* const* filename = files; *filename != 0; ++filename) {
     std::string filepath = std::string("levels/") + *filename;
     if(PHYSFS_isDirectory(filepath.c_str()))
   char** files = PHYSFS_enumerateFiles("levels/");
   for(const char* const* filename = files; *filename != 0; ++filename) {
     std::string filepath = std::string("levels/") + *filename;
     if(PHYSFS_isDirectory(filepath.c_str()))
-      level_subsets.push_back(filepath);
+      level_worlds.push_back(filepath);
   }
   PHYSFS_freeList(files);
 
   free_contrib_menu();
   }
   PHYSFS_freeList(files);
 
   free_contrib_menu();
+  contrib_menu.reset(new Menu());
 
   contrib_menu->add_label(_("Contrib Levels"));
   contrib_menu->add_hl();
 
   contrib_menu->add_label(_("Contrib Levels"));
   contrib_menu->add_hl();
-  
+
   int i = 0;
   int i = 0;
-  for (std::vector<std::string>::iterator it = level_subsets.begin();
-      it != level_subsets.end(); ++it) {
+  for (std::vector<std::string>::iterator it = level_worlds.begin();
+      it != level_worlds.end(); ++it) {
     try {
     try {
-      std::auto_ptr<LevelSubset> subset (new LevelSubset());
-      subset->load(*it);
-      if(subset->hide_from_contribs) {
+      std::auto_ptr<World> world (new World());
+      world->load(*it + "/info");
+      if(world->hide_from_contribs) {
         continue;
       }
         continue;
       }
-      contrib_menu->add_submenu(subset->title, contrib_subset_menu, i++);
-      contrib_subsets.push_back(subset.release());
+      contrib_menu->add_entry(i++, world->title);
+      contrib_worlds.push_back(world.release());
     } catch(std::exception& e) {
 #ifdef DEBUG
     } catch(std::exception& e) {
 #ifdef DEBUG
-      std::cerr << "Couldn't parse levelset info for '"
-        << *it << "': " << e.what() << "\n";
+      log_warning << "Couldn't parse levelset info for '" << *it << "': " << e.what() << std::endl;
 #endif
     }
   }
 #endif
     }
   }
@@ -152,7 +139,8 @@ void generate_contrib_menu()
   contrib_menu->add_back(_("Back"));
 }
 
   contrib_menu->add_back(_("Back"));
 }
 
-std::string get_level_name(const std::string& filename)
+std::string
+TitleScreen::get_level_name(const std::string& filename)
 {
   try {
     lisp::Parser parser;
 {
   try {
     lisp::Parser parser;
@@ -166,290 +154,300 @@ std::string get_level_name(const std::string& filename)
     level->get("name", name);
     return name;
   } catch(std::exception& e) {
     level->get("name", name);
     return name;
   } catch(std::exception& e) {
-    std::cerr << "Problem getting name of '" << filename << "'.\n";
+    log_warning << "Problem getting name of '" << filename << "'." << std::endl;
     return "";
   }
 }
 
     return "";
   }
 }
 
-void check_levels_contrib_menu()
+void
+TitleScreen::check_levels_contrib_menu()
 {
   int index = contrib_menu->check();
   if (index == -1)
     return;
 
 {
   int index = contrib_menu->check();
   if (index == -1)
     return;
 
-  LevelSubset& subset = * (contrib_subsets[index]);
-  
-  if(subset.has_worldmap) {
-    WorldMapNS::WorldMap worldmap;
-    worldmap.set_map_filename(subset.get_worldmap_filename());
-    sound_manager->stop_music();
-
-    // some fading
-    fadeout(256);
-    DrawingContext context;
-    context.draw_text(white_text, "Loading...",
-        Vector(SCREEN_WIDTH/2, SCREEN_HEIGHT/2), CENTER_ALLIGN, LAYER_FOREGROUND1);
-    context.do_drawing();
-
-    // TODO: slots should be available for contrib maps
-    worldmap.loadgame("save/" + subset.name + "-slot1.stsg");
-    worldmap.display();  // run the map
+  current_world = contrib_worlds[index];
 
 
-    Menu::set_current(main_menu);
-    resume_demo();
-  } else if (current_subset != index) {
-    current_subset = index;
-    LevelSubset& subset = * (contrib_subsets[index]);
-
-    current_contrib_subset = &subset;
-
-    contrib_subset_menu->clear();
+  if(!current_world->is_levelset) {
+    update_load_game_menu();
+    Menu::push_current(load_game_menu.get());
+  } else {
+    contrib_world_menu.reset(new Menu());
 
 
-    contrib_subset_menu->add_label(subset.title);
-    contrib_subset_menu->add_hl();
+    contrib_world_menu->add_label(current_world->title);
+    contrib_world_menu->add_hl();
 
 
-    for (int i = 0; i < subset.get_num_levels(); ++i)
+    for (unsigned int i = 0; i < current_world->get_num_levels(); ++i)
     {
       /** get level's title */
     {
       /** get level's title */
-      std::string filename = subset.get_level_filename(i);
+      std::string filename = current_world->get_level_filename(i);
       std::string title = get_level_name(filename);
       std::string title = get_level_name(filename);
-      contrib_subset_menu->add_entry(i, title);
+      contrib_world_menu->add_entry(i, title);
     }
 
     }
 
-    contrib_subset_menu->add_hl();
-    contrib_subset_menu->add_back(_("Back"));
+    contrib_world_menu->add_hl();
+    contrib_world_menu->add_back(_("Back"));
 
 
-    titlesession->get_current_sector()->activate("main");
-    titlesession->set_current();
+    Menu::push_current(contrib_world_menu.get());
   }
 }
 
   }
 }
 
-void check_contrib_subset_menu()
+void
+TitleScreen::check_contrib_world_menu()
 {
 {
-  int index = contrib_subset_menu->check();
+  int index = contrib_world_menu->check();
   if (index != -1) {
   if (index != -1) {
-    if (contrib_subset_menu->get_item_by_id(index).kind == MN_ACTION) {
+    if (contrib_world_menu->get_item_by_id(index).kind == MN_ACTION) {
       sound_manager->stop_music();
       sound_manager->stop_music();
-      GameSession session(
-          current_contrib_subset->get_level_filename(index), ST_GL_PLAY);
-      session.run();
-      player_status->reset();
-      Menu::set_current(main_menu);
-      resume_demo();
+      GameSession* session =
+        new GameSession(current_world->get_level_filename(index));
+      main_loop->push_screen(session);
     }
     }
-  }  
+  }
 }
 
 }
 
-void draw_demo(float elapsed_time)
+void
+TitleScreen::make_tux_jump()
 {
 {
+  static Timer randomWaitTimer;
+  static Timer jumpPushTimer;
   static float last_tux_x_pos = -1;
   static float last_tux_y_pos = -1;
   static float last_tux_x_pos = -1;
   static float last_tux_y_pos = -1;
+
   Sector* sector  = titlesession->get_current_sector();
   Player* tux = sector->player;
 
   Sector* sector  = titlesession->get_current_sector();
   Player* tux = sector->player;
 
-  sector->play_music(LEVEL_MUSIC);
+  //sector->play_music(LEVEL_MUSIC);
 
   controller->update();
   controller->press(Controller::RIGHT);
 
   controller->update();
   controller->press(Controller::RIGHT);
-  
-  if(random_timer.check() || 
-      (walking && fabsf(last_tux_x_pos - tux->get_pos().x)) < .1) {
-    walking = false;
-  } else {
-      if(!walking && fabsf(tux->get_pos().y - last_tux_y_pos) < .1) {
-        random_timer.start(float(rand() % 3000 + 3000) / 1000.);
-        walking = true;
-      }
+
+  // Determine how far we moved since last frame
+  float dx = fabsf(last_tux_x_pos - tux->get_pos().x);
+  float dy = fabsf(last_tux_y_pos - tux->get_pos().y);
+
+  // Calculate space to check for obstacles
+  Rect lookahead = tux->get_bbox();
+  lookahead.move(Vector(96, 0));
+
+  // Check if we should press the jump button
+  bool randomJump = !randomWaitTimer.started();
+  bool notMoving = (fabsf(dx) + fabsf(dy)) < 0.1;
+  bool pathBlocked = !sector->is_free_of_statics(lookahead);
+  if (!controller->released(Controller::JUMP)
+      && (notMoving || pathBlocked || randomJump)) {
+    float jumpDuration;
+    if(pathBlocked)
+      jumpDuration = 0.5;
+    else
+      jumpDuration = systemRandom.randf(0.3, 0.8);
+    jumpPushTimer.start(jumpDuration);
+    randomWaitTimer.start(systemRandom.randf(3.0, 6.0));
   }
   }
-  if(!walking)
+
+  // Keep jump button pressed
+  if (jumpPushTimer.started())
     controller->press(Controller::JUMP);
     controller->press(Controller::JUMP);
+
+  // Remember last position, so we can determine if we moved
   last_tux_x_pos = tux->get_pos().x;
   last_tux_y_pos = tux->get_pos().y;
 
   // Wrap around at the end of the level back to the beginnig
   last_tux_x_pos = tux->get_pos().x;
   last_tux_y_pos = tux->get_pos().y;
 
   // Wrap around at the end of the level back to the beginnig
-  if(sector->solids->get_width() * 32 - 320 < tux->get_pos().x) {
+  if(sector->get_width() - 320 < tux->get_pos().x) {
     sector->activate("main");
     sector->camera->reset(tux->get_pos());
   }
     sector->activate("main");
     sector->camera->reset(tux->get_pos());
   }
-
-  sector->update(elapsed_time);
-  sector->draw(*titlesession->context);
 }
 
 }
 
-/* --- TITLE SCREEN --- */
-void title()
+TitleScreen::TitleScreen()
 {
 {
-  walking = true;
-  //LevelEditor* leveleditor;
-  controller = new CodeController();
+  controller.reset(new CodeController());
+  titlesession.reset(new GameSession("levels/misc/menu.stl"));
 
 
-  titlesession = new GameSession("levels/misc/menu.stl", ST_GL_DEMO_GAME);
+  Player* player = titlesession->get_current_sector()->player;
+  player->set_controller(controller.get());
+
+  main_menu.reset(new Menu());
+  main_menu->set_pos(SCREEN_WIDTH/2, 335);
+  main_menu->add_entry(MNID_STARTGAME, _("Start Game"));
+  main_menu->add_entry(MNID_LEVELS_CONTRIB, _("Contrib Levels"));
+  main_menu->add_submenu(_("Options"), get_options_menu());
+  main_menu->add_entry(MNID_CREDITS, _("Credits"));
+  main_menu->add_entry(MNID_QUITMAINMENU, _("Quit"));
+}
 
 
-  /* Load images: */
-  bkg_title = new Surface("images/background/arctis.jpg");
-  logo = new Surface("images/engine/menu/logo.png");
-  //img_choose_subset = new Surface("images/status/choose-level-subset.png");
+TitleScreen::~TitleScreen()
+{
+}
 
 
-  titlesession->get_current_sector()->activate("main");
-  titlesession->set_current();
+void
+TitleScreen::setup()
+{
+  player_status->reset();
 
 
-  Player* player = titlesession->get_current_sector()->player;
-  player->set_controller(controller);
+  Sector* sector = titlesession->get_current_sector();
+  if(Sector::current() != sector) {
+    sector->play_music(LEVEL_MUSIC);
+    sector->activate(sector->player->get_pos());
+  }
 
 
-  /* --- Main title loop: --- */
-  frame = 0;
+  Menu::set_current(main_menu.get());
+}
 
 
-  random_timer.start(float(rand() % 2000 + 2000) / 1000.0);
+void
+TitleScreen::leave()
+{
+  Sector* sector = titlesession->get_current_sector();
+  sector->deactivate();
+  Menu::set_current(NULL);
+}
 
 
-  Uint32 lastticks = SDL_GetTicks();
-  
-  Menu::set_current(main_menu);
-  DrawingContext& context = *titlesession->context;
-  bool running = true;
-  while (running)
-    {
-      // Calculate the movement-factor
-      Uint32 ticks = SDL_GetTicks();
-      float elapsed_time = float(ticks - lastticks) / 1000.;
-      game_time += elapsed_time;
-      lastticks = ticks;
-      // 40fps is minimum
-      if(elapsed_time > .04)
-        elapsed_time = .04;
-      
-      /* Lower the speed so that Tux doesn't jump too hectically throught
-         the demo. */
-      elapsed_time /= 2;
-
-      SDL_Event event;
-      main_controller->update();
-      while (SDL_PollEvent(&event)) {
-        if (Menu::current()) {
-          Menu::current()->event(event);
-        }
-        main_controller->process_event(event);
-        if (event.type == SDL_QUIT)
-          throw graceful_shutdown();
-      }
-  
-      /* Draw the background: */
-      draw_demo(elapsed_time);
-
-      if (Menu::current() == main_menu)
-        context.draw_surface(logo, Vector(SCREEN_WIDTH/2 - logo->get_width()/2, 30),
-            LAYER_FOREGROUND1+1);
-
-      context.draw_text(white_small_text, " SuperTux " PACKAGE_VERSION "\n",
-              Vector(0, SCREEN_HEIGHT - 50), LEFT_ALLIGN, LAYER_FOREGROUND1);
-      context.draw_text(white_small_text,
-        _(
+void
+TitleScreen::draw(DrawingContext& context)
+{
+  Sector* sector  = titlesession->get_current_sector();
+  sector->draw(context);
+
+  context.draw_text(white_small_text, " SuperTux " PACKAGE_VERSION "\n",
+      Vector(0, SCREEN_HEIGHT - 50), LEFT_ALLIGN, LAYER_FOREGROUND1);
+  context.draw_text(white_small_text,
+      _(
 "Copyright (c) 2006 SuperTux Devel Team\n"
 "This game comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to\n"
 "redistribute it under certain conditions; see the file COPYING for details.\n"
 "Copyright (c) 2006 SuperTux Devel Team\n"
 "This game comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to\n"
 "redistribute it under certain conditions; see the file COPYING for details.\n"
-        ),
-        Vector(0, SCREEN_HEIGHT - 50 + white_small_text->get_height() + 5),
-        LEFT_ALLIGN, LAYER_FOREGROUND1);
-
-      /* Don't draw menu, if quit is true */
-      Menu* menu = Menu::current();
-      if(menu)
-        {
-          menu->draw(context);
-          menu->update();
-         
-          if(menu == main_menu)
-            {
-              switch (main_menu->check())
-                {
-                case MNID_STARTGAME:
-                  // Start Game, ie. goto the slots menu
-                  update_load_save_game_menu(load_game_menu);
-                  break;
-                case MNID_LEVELS_CONTRIB:
-                  // Contrib Menu
-                  generate_contrib_menu();
-                  break;
-#if 0
-                case MNID_LEVELEDITOR: {
-                  LevelEdtiro* leveleditor = new LevelEditor();
-                  leveleditor->run();
-                  delete leveleditor;
-                  Menu::set_current(main_menu);
-                  resume_demo();
-                  break;
-                }
-#endif
-                case MNID_CREDITS:
-                  sound_manager->stop_music();
-                  fadeout(500);
-                  sound_manager->play_music("music/credits.ogg");
-                  display_text_file("credits.txt");
-                  sound_manager->stop_music();
-                  fadeout(500);
-                  Menu::set_current(main_menu);
-                  break;
-                case MNID_QUITMAINMENU:
-                  running = false;
-                  break;
-                }
-            }
-          else if(menu == options_menu)
-            {
-              process_options_menu();
-            }
-          else if(menu == load_game_menu)
-            {
-              if(event.key.keysym.sym == SDLK_DELETE)
-                {
-                int slot = menu->get_active_item_id();
-                std::stringstream stream;
-                stream << slot;
-                std::string str = _("Are you sure you want to delete slot") + stream.str() + "?";
-                
-                if(confirm_dialog(bkg_title, str.c_str())) {
-                  str = "save/slot" + stream.str() + ".stsg";
-                  printf("Removing: %s\n",str.c_str());
-                  PHYSFS_delete(str.c_str());
-                }
-
-                update_load_save_game_menu(load_game_menu);
-                Menu::set_current(main_menu);
-                resume_demo();
-                }
-              else if (process_load_game_menu())
-                {
-                  resume_demo();
-                }
-            }
-          else if(menu == contrib_menu)
-            {
-              check_levels_contrib_menu();
-            }
-          else if (menu == contrib_subset_menu)
-            {
-              check_contrib_subset_menu();
-            }
-        }
+),
+      Vector(0, SCREEN_HEIGHT - 50 + white_small_text->get_height() + 5),
+      LEFT_ALLIGN, LAYER_FOREGROUND1);
+}
+
+void
+TitleScreen::update(float elapsed_time)
+{
+  main_loop->set_speed(0.6);
+  Sector* sector  = titlesession->get_current_sector();
+  sector->update(elapsed_time);
 
 
-      // reopen menu of user closed it (so that the app doesn't close when user
-      // accidently hit ESC)
-      if(Menu::current() == 0) {
-        Menu::set_current(main_menu);
+  make_tux_jump();
+
+  Menu* menu = Menu::current();
+  if(menu) {
+    menu->update();
+
+    if(menu == main_menu.get()) {
+      switch (main_menu->check()) {
+        case MNID_STARTGAME:
+          // Start Game, ie. goto the slots menu
+          if(main_world.get() == NULL) {
+            main_world.reset(new World());
+            main_world->load("levels/world1/info");
+          }
+          current_world = main_world.get();
+          update_load_game_menu();
+          Menu::push_current(load_game_menu.get());
+          break;
+        case MNID_LEVELS_CONTRIB:
+          // Contrib Menu
+          generate_contrib_menu();
+          Menu::push_current(contrib_menu.get());
+          break;
+        case MNID_CREDITS:
+          main_loop->push_screen(new TextScroller("credits.txt"),
+                                 new FadeOut(0.5));
+          break;
+        case MNID_QUITMAINMENU:
+          main_loop->quit(new FadeOut(0.25));
+          break;
       }
       }
+    } else if(menu == load_game_menu.get()) {
+      /*
+      if(event.key.keysym.sym == SDLK_DELETE) {
+        int slot = menu->get_active_item_id();
+        std::stringstream stream;
+        stream << slot;
+        std::string str = _("Are you sure you want to delete slot") + stream.str() + "?";
+
+        if(confirm_dialog(bkg_title, str.c_str())) {
+          str = "save/slot" + stream.str() + ".stsg";
+          log_debug << "Removing: " << str << std::endl;
+          PHYSFS_delete(str.c_str());
+        }
 
 
-      context.do_drawing();
-      sound_manager->update();
+        update_load_save_game_menu(load_game_menu);
+        Menu::set_current(main_menu.get());
+      }*/
+      process_load_game_menu();
+    } else if(menu == contrib_menu.get()) {
+      check_levels_contrib_menu();
+    } else if (menu == contrib_world_menu.get()) {
+      check_contrib_world_menu();
+    }
+  }
 
 
-      //frame_rate.update();
+  // reopen menu of user closed it (so that the app doesn't close when user
+  // accidently hit ESC)
+  if(Menu::current() == 0) {
+    Menu::set_current(main_menu.get());
+  }
+}
 
 
-      /* Pause: */
-      frame++;
-    }
-  /* Free surfaces: */
+std::string
+TitleScreen::get_slotinfo(int slot)
+{
+  std::string tmp;
+  std::string title;
 
 
-  free_contrib_menu();
-  delete titlesession;
-  delete bkg_title;
-  delete logo;
-  //delete img_choose_subset;
+  std::string basename = current_world->get_basedir();
+  basename = basename.substr(0, basename.length()-1);
+  std::string worlddirname = FileSystem::basename(basename);
+  std::ostringstream stream;
+  stream << "save/" << worlddirname << "_" << slot << ".stsg";
+  std::string slotfile = stream.str();
+
+  try {
+    lisp::Parser parser;
+    std::auto_ptr<lisp::Lisp> root (parser.parse(slotfile));
+
+    const lisp::Lisp* savegame = root->get_lisp("supertux-savegame");
+    if(!savegame)
+      throw std::runtime_error("file is not a supertux-savegame.");
+
+    savegame->get("title", title);
+  } catch(std::exception& e) {
+    std::ostringstream slottitle;
+    slottitle << _("Slot") << " " << slot << " - " << _("Free");
+    return slottitle.str();
+  }
+
+  std::ostringstream slottitle;
+  slottitle << _("Slot") << " " << slot << " - " << title;
+  return slottitle.str();
+}
+
+bool
+TitleScreen::process_load_game_menu()
+{
+  int slot = load_game_menu->check();
+
+  if(slot == -1)
+    return false;
+
+  if(load_game_menu->get_item_by_id(slot).kind != MN_ACTION)
+    return false;
+
+  std::string basename = current_world->get_basedir();
+  basename = basename.substr(0, basename.length()-1);
+  std::string worlddirname = FileSystem::basename(basename);
+  std::stringstream stream;
+  stream << "save/" << worlddirname << "_" << slot << ".stsg";
+  std::string slotfile = stream.str();
+
+  try {
+    current_world->set_savegame_filename(slotfile);
+    current_world->run();
+  } catch(std::exception& e) {
+    log_fatal << "Couldn't start world: " << e.what() << std::endl;
+  }
+
+  return true;
 }
 }