Let Tux bounce off badguys when he's invincible. This let's us bounce off guys like...
[supertux.git] / src / title.cpp
index f4d6ea0..5b31fe3 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"
-#include "msg.hpp"
-
-static Surface* bkg_title;
-static Surface* logo;
-//static Surface* img_choose_subset;
-
-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)
-{
-  msg_debug("update loadsavemenu");
-  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();
   
   int i = 0;
 
   contrib_menu->add_label(_("Contrib Levels"));
   contrib_menu->add_hl();
   
   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
-      msg_warning("Couldn't parse levelset info for '"
-        << *it << "': " << e.what() << "");
+      log_warning << "Couldn't parse levelset info for '" << *it << "': " << e.what() << std::endl;
 #endif
     }
   }
 #endif
     }
   }
@@ -150,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;
@@ -164,92 +154,70 @@ 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) {
-    msg_warning("Problem getting name of '" << filename << "'.");
+    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
-
-    Menu::set_current(main_menu);
-    resume_demo();
-  } else if (current_subset != index) {
-    current_subset = index;
-    LevelSubset& subset = * (contrib_subsets[index]);
+  current_world = contrib_worlds[index];
 
 
-    current_contrib_subset = &subset;
+  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->clear();
+    contrib_world_menu->add_label(current_world->title);
+    contrib_world_menu->add_hl();
 
 
-    contrib_subset_menu->add_label(subset.title);
-    contrib_subset_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 Timer randomWaitTimer;
   static Timer jumpPushTimer;
-  static Timer jumpRecoverTimer;
   static float last_tux_x_pos = -1;
   static float last_tux_y_pos = -1;
 
   Sector* sector  = titlesession->get_current_sector();
   Player* tux = sector->player;
 
   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->play_music(LEVEL_MUSIC);
+  //sector->play_music(LEVEL_MUSIC);
 
   controller->update();
   controller->press(Controller::RIGHT);
 
   controller->update();
   controller->press(Controller::RIGHT);
@@ -259,23 +227,27 @@ void draw_demo(float elapsed_time)
   float dy = fabsf(last_tux_y_pos - tux->get_pos().y); 
  
   // Calculate space to check for obstacles 
   float dy = fabsf(last_tux_y_pos - tux->get_pos().y); 
  
   // Calculate space to check for obstacles 
-  Rect lookahead = Rect(tux->get_bbox());
-  lookahead.move(Vector(lookahead.get_width()*2,0));
+  Rect lookahead = tux->get_bbox();
+  lookahead.move(Vector(96, 0));
   
   // Check if we should press the jump button
   bool randomJump = !randomWaitTimer.started();
   
   // Check if we should press the jump button
   bool randomJump = !randomWaitTimer.started();
-  bool mayJump = !jumpRecoverTimer.started();
-  bool notMoving = (dx+dy < 0.1);
+  bool notMoving = (fabsf(dx) + fabsf(dy)) < 0.1;
   bool pathBlocked = !sector->is_free_space(lookahead); 
   bool pathBlocked = !sector->is_free_space(lookahead); 
-  if ((notMoving || pathBlocked || randomJump) && mayJump) {
-    float jumpDuration = float(rand() % 200 + 500) / 1000.0;
+  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);
     jumpPushTimer.start(jumpDuration);
-    jumpRecoverTimer.start(jumpDuration+0.1);
-    randomWaitTimer.start(float(rand() % 3000 + 3000) / 1000.0);
+    randomWaitTimer.start(systemRandom.randf(3.0, 6.0));
   }
 
   // Keep jump button pressed
   }
 
   // Keep jump button pressed
-  if (jumpPushTimer.started()) controller->press(Controller::JUMP);
+  if (jumpPushTimer.started())
+    controller->press(Controller::JUMP);
 
   // Remember last position, so we can determine if we moved
   last_tux_x_pos = tux->get_pos().x;
 
   // Remember last position, so we can determine if we moved
   last_tux_x_pos = tux->get_pos().x;
@@ -286,172 +258,197 @@ void draw_demo(float elapsed_time)
     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()
 {
 {
-  //LevelEditor* leveleditor;
-  controller = new CodeController();
-
-  titlesession = new GameSession("levels/misc/menu.stl", ST_GL_DEMO_GAME);
+  controller.reset(new CodeController());
+  titlesession.reset(new GameSession("levels/misc/menu.stl"));
 
 
-  /* 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");
+  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"));
+}
 
 
-  titlesession->get_current_sector()->activate("main");
-  titlesession->set_current();
+TitleScreen::~TitleScreen()
+{
+}
 
 
-  Player* player = titlesession->get_current_sector()->player;
-  player->set_controller(controller);
+void
+TitleScreen::setup()
+{
+  player_status->reset();
 
 
-  /* --- Main title loop: --- */
-  frame = 0;
+  Sector* sector = titlesession->get_current_sector();
+  if(Sector::current() != sector) {
+    sector->play_music(LEVEL_MUSIC);
+    sector->activate(sector->player->get_pos());
+  }
 
 
-  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);
+  Menu::set_current(main_menu.get());
+}
 
 
-      if (Menu::current() == main_menu)
-        context.draw_surface(logo, Vector(SCREEN_WIDTH/2 - logo->get_width()/2, 30),
-            LAYER_FOREGROUND1+1);
+void
+TitleScreen::leave()
+{
+  Sector* sector = titlesession->get_current_sector();
+  sector->deactivate();
+  Menu::set_current(NULL);
+}
 
 
-      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();
+),
+      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);
+
+  make_tux_jump();
+  
+  Menu* menu = Menu::current();
+  if(menu) {
+    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;
-                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";
-                  msg_debug("Removing: " << 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();
-            }
+    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());
         }
 
         }
 
-      // 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);
-      }
+        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();
+    }
+  }
 
 
-      context.do_drawing();
-      sound_manager->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());
+  }
+}
 
 
-      //frame_rate.update();
+std::string
+TitleScreen::get_slotinfo(int slot)
+{
+  std::string tmp;
+  std::string title;
 
 
-      /* Pause: */
-      frame++;
-    }
-  /* Free surfaces: */
+  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();
 
 
-  free_contrib_menu();
-  delete titlesession;
-  delete bkg_title;
-  delete logo;
-  //delete img_choose_subset;
+  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;
 }
 }
+