Renamed MainLoop to ScreenManager
authorIngo Ruhnke <grumbel@gmx.de>
Thu, 19 Nov 2009 16:50:58 +0000 (16:50 +0000)
committerIngo Ruhnke <grumbel@gmx.de>
Thu, 19 Nov 2009 16:50:58 +0000 (16:50 +0000)
SVN-Revision: 6050

src/supertux/game_session.cpp
src/supertux/levelintro.cpp
src/supertux/main.cpp
src/supertux/mainloop.cpp [deleted file]
src/supertux/mainloop.hpp [deleted file]
src/supertux/menu/contrib_world_menu.cpp
src/supertux/screen_manager.cpp [new file with mode: 0644]
src/supertux/screen_manager.hpp [new file with mode: 0644]
src/supertux/textscroller.cpp
src/supertux/title_screen.cpp
src/supertux/world.cpp

index 001b5e7..94eedd5 100644 (file)
@@ -34,7 +34,7 @@
 #include "supertux/gameconfig.hpp"
 #include "supertux/levelintro.hpp"
 #include "supertux/globals.hpp"
-#include "supertux/mainloop.hpp"
+#include "supertux/screen_manager.hpp"
 #include "supertux/menu/menu_storage.hpp"
 #include "supertux/menu/game_menu.hpp"
 #include "supertux/menu/options_menu.hpp"
@@ -71,7 +71,7 @@ GameSession::GameSession(const std::string& levelfile_, Statistics* statistics)
   currentsector = NULL;
 
   game_pause = false;
-  speed_before_pause = g_main_loop->get_speed();
+  speed_before_pause = g_screen_manager->get_speed();
 
   statistics_backdrop.reset(new Surface("images/engine/menu/score-backdrop.png"));
 
@@ -122,7 +122,7 @@ GameSession::restart_level()
     }
   } catch(std::exception& e) {
     log_fatal << "Couldn't start level: " << e.what() << std::endl;
-    g_main_loop->exit_screen();
+    g_screen_manager->exit_screen();
   }
 
   sound_manager->stop_music();
@@ -236,8 +236,8 @@ GameSession::toggle_pause()
 {
   // pause
   if(!game_pause) {
-    speed_before_pause = g_main_loop->get_speed();
-    g_main_loop->set_speed(0);
+    speed_before_pause = g_screen_manager->get_speed();
+    g_screen_manager->set_speed(0);
     MenuManager::set_current(game_menu.get());
     game_menu->set_active_item(MNID_CONTINUE);
     game_pause = true;
@@ -393,7 +393,7 @@ GameSession::process_menu()
           break;
         case MNID_ABORTLEVEL:
           MenuManager::set_current(0);
-          g_main_loop->exit_screen();
+          g_screen_manager->exit_screen();
           break;
       }
     }
@@ -415,7 +415,7 @@ GameSession::setup()
 
   if (!levelintro_shown) {
     levelintro_shown = true;
-    g_main_loop->push_screen(new LevelIntro(level.get(), best_level_statistics));
+    g_screen_manager->push_screen(new LevelIntro(level.get(), best_level_statistics));
   }
 }
 
@@ -431,7 +431,7 @@ GameSession::update(float elapsed_time)
 
   // Unpause the game if the menu has been closed
   if (game_pause && !MenuManager::current()) {
-    g_main_loop->set_speed(speed_before_pause);
+    g_screen_manager->set_speed(speed_before_pause);
     game_pause = false;
   }
 
@@ -504,7 +504,7 @@ GameSession::finish(bool win)
       WorldMap::current()->finished_level(level.get());
   }
 
-  g_main_loop->exit_screen();
+  g_screen_manager->exit_screen();
 }
 
 void
@@ -564,7 +564,7 @@ GameSession::start_sequence(const std::string& sequencename)
   }
 
   /* slow down the game for end-sequence */
-  g_main_loop->set_speed(0.5f);
+  g_screen_manager->set_speed(0.5f);
 
   currentsector->add_object(end_sequence);
   end_sequence->start();
index 8216995..f7cb7d8 100644 (file)
@@ -21,7 +21,7 @@
 #include "sprite/sprite_manager.hpp"
 #include "supertux/fadeout.hpp"
 #include "supertux/globals.hpp"
-#include "supertux/mainloop.hpp"
+#include "supertux/screen_manager.hpp"
 #include "supertux/resources.hpp"
 #include "util/gettext.hpp"
 
@@ -56,7 +56,7 @@ LevelIntro::update(float elapsed_time)
      || g_main_controller->pressed(Controller::ACTION)
      || g_main_controller->pressed(Controller::MENU_SELECT)
      || g_main_controller->pressed(Controller::PAUSE_MENU)) {
-    g_main_loop->exit_screen(new FadeOut(0.1));
+    g_screen_manager->exit_screen(new FadeOut(0.1));
   }
 
   player_sprite_py += player_sprite_vy * elapsed_time;
index 10744f3..0314797 100644 (file)
@@ -42,7 +42,7 @@ namespace supertux_apple {
 #include "scripting/squirrel_util.hpp"
 #include "supertux/gameconfig.hpp"
 #include "supertux/globals.hpp"
-#include "supertux/mainloop.hpp"
+#include "supertux/screen_manager.hpp"
 #include "supertux/resources.hpp"
 #include "supertux/title_screen.hpp"
 #include "util/file_system.hpp"
@@ -499,7 +499,7 @@ Main::wait_for_event(float min_delay, float max_delay)
     while(SDL_PollEvent(&event)) {
       switch(event.type) {
         case SDL_QUIT:
-          g_main_loop->quit();
+          g_screen_manager->quit();
           break;
         case SDL_KEYDOWN:
         case SDL_JOYBUTTONDOWN:
@@ -583,7 +583,7 @@ Main::main(int argc, char** argv)
 
     timelog(0);
 
-    g_main_loop = new MainLoop();
+    g_screen_manager = new ScreenManager();
     if(g_config->start_level != "") {
       // we have a normal path specified at commandline, not a physfs path.
       // So we simply mount that path here...
@@ -594,7 +594,7 @@ Main::main(int argc, char** argv)
       if(g_config->start_level.size() > 4 &&
          g_config->start_level.compare(g_config->start_level.size() - 5, 5, ".stwm") == 0) {
         init_rand();
-        g_main_loop->push_screen(new WorldMapNS::WorldMap(
+        g_screen_manager->push_screen(new WorldMapNS::WorldMap(
                                  FileSystem::basename(g_config->start_level)));
       } else {
         init_rand();//If level uses random eg. for
@@ -610,15 +610,15 @@ Main::main(int argc, char** argv)
 
         if(g_config->record_demo != "")
           session->record_demo(g_config->record_demo);
-        g_main_loop->push_screen(session.release());
+        g_screen_manager->push_screen(session.release());
       }
     } else {
       init_rand();
-      g_main_loop->push_screen(new TitleScreen());
+      g_screen_manager->push_screen(new TitleScreen());
     }
 
     //init_rand(); PAK: this call might subsume the above 3, but I'm chicken!
-    g_main_loop->run(context);
+    g_screen_manager->run(context);
   } catch(std::exception& e) {
     log_fatal << "Unexpected exception: " << e.what() << std::endl;
     result = 1;
@@ -627,8 +627,8 @@ Main::main(int argc, char** argv)
     result = 1;
   }
 
-  delete g_main_loop;
-  g_main_loop = NULL;
+  delete g_screen_manager;
+  g_screen_manager = NULL;
 
   Resources::unload_shared();
   quit_audio();
diff --git a/src/supertux/mainloop.cpp b/src/supertux/mainloop.cpp
deleted file mode 100644 (file)
index c5ac1f6..0000000
+++ /dev/null
@@ -1,342 +0,0 @@
-//  SuperTux
-//  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 as published by
-//  the Free Software Foundation, either version 3 of the License, or
-//  (at your option) any later version.
-//
-//  This program is distributed in the hope that it will be useful,
-//  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, see <http://www.gnu.org/licenses/>.
-
-#include "supertux/mainloop.hpp"
-
-#include "audio/sound_manager.hpp"
-#include "control/joystickkeyboardcontroller.hpp"
-#include "gui/menu.hpp"
-#include "gui/menu_manager.hpp"
-#include "scripting/squirrel_util.hpp"
-#include "scripting/time_scheduler.hpp"
-#include "supertux/constants.hpp"
-#include "supertux/console.hpp"
-#include "supertux/gameconfig.hpp"
-#include "supertux/globals.hpp"
-#include "supertux/main.hpp"
-#include "supertux/player_status.hpp"
-#include "supertux/resources.hpp"
-#include "supertux/screen_fade.hpp"
-#include "supertux/screen.hpp"
-#include "supertux/timer.hpp"
-#include "video/drawing_context.hpp"
-#include "video/renderer.hpp"
-
-/** ticks (as returned from SDL_GetTicks) per frame */
-static const Uint32 TICKS_PER_FRAME = (Uint32) (1000.0 / LOGICAL_FPS);
-/** don't skip more than every 2nd frame */
-static const int MAX_FRAME_SKIP = 2;
-
-float g_game_speed = 1.0f;
-
-MainLoop* g_main_loop = NULL;
-
-MainLoop::MainLoop() :
-  waiting_threads(),
-  running(),
-  speed(1.0), 
-  nextpop(false), 
-  nextpush(false), 
-  fps(0), 
-  next_screen(),
-  current_screen(),
-  console(),
-  screen_fade(),
-  screen_stack(),
-  screenshot_requested(false)
-{
-  using namespace Scripting;
-  TimeScheduler::instance = new TimeScheduler();
-}
-
-MainLoop::~MainLoop()
-{
-  using namespace Scripting;
-  delete TimeScheduler::instance;
-  TimeScheduler::instance = NULL;
-
-  for(std::vector<Screen*>::iterator i = screen_stack.begin();
-      i != screen_stack.end(); ++i) {
-    delete *i;
-  }
-}
-
-void
-MainLoop::push_screen(Screen* screen, ScreenFade* screen_fade)
-{
-  this->next_screen.reset(screen);
-  this->screen_fade.reset(screen_fade);
-  nextpush = !nextpop;
-  nextpop = false;
-  speed = 1.0f;
-}
-
-void
-MainLoop::exit_screen(ScreenFade* screen_fade)
-{
-  next_screen.reset(NULL);
-  this->screen_fade.reset(screen_fade);
-  nextpop = true;
-  nextpush = false;
-}
-
-void
-MainLoop::set_screen_fade(ScreenFade* screen_fade)
-{
-  this->screen_fade.reset(screen_fade);
-}
-
-void
-MainLoop::quit(ScreenFade* screen_fade)
-{
-  for(std::vector<Screen*>::iterator i = screen_stack.begin();
-      i != screen_stack.end(); ++i)
-    delete *i;
-  screen_stack.clear();
-
-  exit_screen(screen_fade);
-}
-
-void
-MainLoop::set_speed(float speed)
-{
-  this->speed = speed;
-}
-
-float
-MainLoop::get_speed() const
-{
-  return speed;
-}
-
-bool
-MainLoop::has_no_pending_fadeout() const
-{
-  return screen_fade.get() == NULL || screen_fade->done();
-}
-
-void
-MainLoop::draw_fps(DrawingContext& context, float fps_fps)
-{
-  char str[60];
-  snprintf(str, sizeof(str), "%3.1f", fps_fps);
-  const char* fpstext = "FPS";
-  context.draw_text(Resources::small_font, fpstext, 
-                    Vector(SCREEN_WIDTH - Resources::small_font->get_text_width(fpstext) - Resources::small_font->get_text_width(" 99999") - BORDER_X, 
-                           BORDER_Y + 20), ALIGN_LEFT, LAYER_HUD);
-  context.draw_text(Resources::small_font, str, Vector(SCREEN_WIDTH - BORDER_X, BORDER_Y + 20), ALIGN_RIGHT, LAYER_HUD);
-}
-
-void
-MainLoop::draw(DrawingContext& context)
-{
-  static Uint32 fps_ticks = SDL_GetTicks();
-  static int frame_count = 0;
-
-  current_screen->draw(context);
-  if(MenuManager::current() != NULL)
-    MenuManager::current()->draw(context);
-  if(screen_fade.get() != NULL)
-    screen_fade->draw(context);
-  Console::instance->draw(context);
-
-  if(g_config->show_fps)
-    draw_fps(context, fps);
-
-  // if a screenshot was requested, pass request on to drawing_context
-  if (screenshot_requested) {
-    context.take_screenshot();
-    screenshot_requested = false;
-  }
-  context.do_drawing();
-
-  /* Calculate frames per second */
-  if(g_config->show_fps)
-  {
-    ++frame_count;
-
-    if(SDL_GetTicks() - fps_ticks >= 500)
-    {
-      fps = (float) frame_count / .5;
-      frame_count = 0;
-      fps_ticks = SDL_GetTicks();
-    }
-  }
-}
-
-void
-MainLoop::update_gamelogic(float elapsed_time)
-{
-  Scripting::update_debugger();
-  Scripting::TimeScheduler::instance->update(game_time);
-  current_screen->update(elapsed_time);
-  if (MenuManager::current() != NULL)
-    MenuManager::current()->update();
-  if(screen_fade.get() != NULL)
-    screen_fade->update(elapsed_time);
-  Console::instance->update(elapsed_time);
-}
-
-void
-MainLoop::process_events()
-{
-  g_main_controller->update();
-  Uint8* keystate = SDL_GetKeyState(NULL);
-  SDL_Event event;
-  while(SDL_PollEvent(&event)) 
-  {
-    g_main_controller->process_event(event);
-
-    if(MenuManager::current() != NULL)
-      MenuManager::current()->event(event);
-
-    switch(event.type)
-    {
-      case SDL_QUIT:
-        quit();
-        break;
-              
-      case SDL_VIDEORESIZE:
-        Renderer::instance()->resize(event.resize.w, event.resize.h);
-        MenuManager::recalc_pos();
-        break;
-            
-      case SDL_KEYDOWN:
-        if (event.key.keysym.sym == SDLK_F10)
-        {
-          g_config->show_fps = !g_config->show_fps;
-        }
-        if (event.key.keysym.sym == SDLK_F11) 
-        {
-          g_config->use_fullscreen = !g_config->use_fullscreen;
-          Renderer::instance()->apply_config();
-          MenuManager::recalc_pos();
-        }
-        else if (event.key.keysym.sym == SDLK_PRINT ||
-                 event.key.keysym.sym == SDLK_F12)
-        {
-          take_screenshot();
-        }
-        else if (event.key.keysym.sym == SDLK_F1 &&
-                 (keystate[SDLK_LCTRL] || keystate[SDLK_RCTRL]) &&
-                 keystate[SDLK_c])
-        {
-          Console::instance->toggle();
-          g_config->console_enabled = true;
-          g_config->save();
-        }
-        break;
-    }
-  }
-}
-
-void
-MainLoop::handle_screen_switch()
-{
-  while( (next_screen.get() != NULL || nextpop) &&
-         has_no_pending_fadeout()) {
-    if(current_screen.get() != NULL) {
-      current_screen->leave();
-    }
-
-    if(nextpop) {
-      if(screen_stack.empty()) {
-        running = false;
-        break;
-      }
-      next_screen.reset(screen_stack.back());
-      screen_stack.pop_back();
-    }
-    if(nextpush && current_screen.get() != NULL) {
-      screen_stack.push_back(current_screen.release());
-    }
-
-    nextpush = false;
-    nextpop = false;
-    speed = 1.0;
-    Screen* next_screen_ptr = next_screen.release();
-    next_screen.reset(0);
-    if(next_screen_ptr)
-      next_screen_ptr->setup();
-    current_screen.reset(next_screen_ptr);
-    screen_fade.reset(NULL);
-
-    waiting_threads.wakeup();
-  }
-}
-
-void
-MainLoop::run(DrawingContext &context)
-{
-  Uint32 last_ticks = 0;
-  Uint32 elapsed_ticks = 0;
-
-  running = true;
-  while(running) {
-
-    handle_screen_switch();
-    if(!running || current_screen.get() == NULL)
-      break;
-
-    Uint32 ticks = SDL_GetTicks();
-    elapsed_ticks += ticks - last_ticks;
-    last_ticks = ticks;
-
-    Uint32 ticks_per_frame = (Uint32) (TICKS_PER_FRAME * g_game_speed);
-
-    if (elapsed_ticks > ticks_per_frame*4) {
-      // when the game loads up or levels are switched the
-      // elapsed_ticks grows extremely large, so we just ignore those
-      // large time jumps
-      elapsed_ticks = 0;
-    }
-
-    if(elapsed_ticks < ticks_per_frame)
-    {
-      Uint32 delay_ticks = ticks_per_frame - elapsed_ticks;
-      SDL_Delay(delay_ticks);
-      last_ticks += delay_ticks;
-      elapsed_ticks += delay_ticks;
-    }
-
-    int frames = 0;
-
-    while(elapsed_ticks >= ticks_per_frame && frames < MAX_FRAME_SKIP) 
-    {
-      elapsed_ticks -= ticks_per_frame;
-      float timestep = 1.0 / LOGICAL_FPS;
-      real_time += timestep;
-      timestep *= speed;
-      game_time += timestep;
-
-      process_events();
-      update_gamelogic(timestep);
-      frames += 1;
-    }
-
-    draw(context);
-
-    sound_manager->update();
-  }
-}
-
-void 
-MainLoop::take_screenshot()
-{
-  screenshot_requested = true;
-}
-
-/* EOF */
diff --git a/src/supertux/mainloop.hpp b/src/supertux/mainloop.hpp
deleted file mode 100644 (file)
index 7f7b78f..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-//  SuperTux
-//  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 as published by
-//  the Free Software Foundation, either version 3 of the License, or
-//  (at your option) any later version.
-//
-//  This program is distributed in the hope that it will be useful,
-//  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, see <http://www.gnu.org/licenses/>.
-
-#ifndef HEADER_SUPERTUX_SUPERTUX_MAINLOOP_HPP
-#define HEADER_SUPERTUX_SUPERTUX_MAINLOOP_HPP
-
-#include <memory>
-
-#include "scripting/thread_queue.hpp"
-
-class Screen;
-class Console;
-class ScreenFade;
-class DrawingContext;
-
-/**
- * Manages, updates and draws all Screens, Controllers, Menus and the Console.
- */
-class MainLoop
-{
-public:
-  MainLoop();
-  ~MainLoop();
-
-  void run(DrawingContext &context);
-  void exit_screen(ScreenFade* fade = NULL);
-  void quit(ScreenFade* fade = NULL);
-  void set_speed(float speed);
-  float get_speed() const;
-  bool has_no_pending_fadeout() const;
-
-  /**
-   * requests that a screenshot be taken after the next frame has been rendered
-   */
-  void take_screenshot();
-
-  // push new screen on screen_stack
-  void push_screen(Screen* screen, ScreenFade* fade = NULL);
-  void set_screen_fade(ScreenFade* fade);
-
-  /// threads that wait for a screenswitch
-  Scripting::ThreadQueue waiting_threads;
-
-private:
-  void draw_fps(DrawingContext& context, float fps);
-  void draw(DrawingContext& context);
-  void update_gamelogic(float elapsed_time);
-  void process_events();
-  void handle_screen_switch();
-
-private:
-  bool running;
-  float speed;
-  bool nextpop;
-  bool nextpush;
-  /// measured fps
-  float fps;
-  std::auto_ptr<Screen> next_screen;
-  std::auto_ptr<Screen> current_screen;
-  std::auto_ptr<Console> console;
-  std::auto_ptr<ScreenFade> screen_fade;
-  std::vector<Screen*> screen_stack;
-  bool screenshot_requested; /**< true if a screenshot should be taken after the next frame has been rendered */
-};
-
-extern MainLoop* g_main_loop;
-
-#endif
-
-/* EOF */
index fdb84c5..b3e0fe1 100644 (file)
@@ -18,7 +18,7 @@
 
 #include "audio/sound_manager.hpp"
 #include "gui/menu_item.hpp"
-#include "supertux/mainloop.hpp"
+#include "supertux/screen_manager.hpp"
 #include "supertux/title_screen.hpp"
 #include "supertux/world.hpp"
 #include "util/gettext.hpp"
@@ -50,7 +50,7 @@ ContribWorldMenu::check_menu()
     {
       sound_manager->stop_music();
       GameSession* session = new GameSession(m_current_world.get_level_filename(index));
-      g_main_loop->push_screen(session);
+      g_screen_manager->push_screen(session);
     }
   }
 }
diff --git a/src/supertux/screen_manager.cpp b/src/supertux/screen_manager.cpp
new file mode 100644 (file)
index 0000000..2b4478e
--- /dev/null
@@ -0,0 +1,342 @@
+//  SuperTux
+//  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 as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  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, see <http://www.gnu.org/licenses/>.
+
+#include "supertux/screen_manager.hpp"
+
+#include "audio/sound_manager.hpp"
+#include "control/joystickkeyboardcontroller.hpp"
+#include "gui/menu.hpp"
+#include "gui/menu_manager.hpp"
+#include "scripting/squirrel_util.hpp"
+#include "scripting/time_scheduler.hpp"
+#include "supertux/constants.hpp"
+#include "supertux/console.hpp"
+#include "supertux/gameconfig.hpp"
+#include "supertux/globals.hpp"
+#include "supertux/main.hpp"
+#include "supertux/player_status.hpp"
+#include "supertux/resources.hpp"
+#include "supertux/screen_fade.hpp"
+#include "supertux/screen.hpp"
+#include "supertux/timer.hpp"
+#include "video/drawing_context.hpp"
+#include "video/renderer.hpp"
+
+/** ticks (as returned from SDL_GetTicks) per frame */
+static const Uint32 TICKS_PER_FRAME = (Uint32) (1000.0 / LOGICAL_FPS);
+/** don't skip more than every 2nd frame */
+static const int MAX_FRAME_SKIP = 2;
+
+float g_game_speed = 1.0f;
+
+ScreenManager* g_screen_manager = NULL;
+
+ScreenManager::ScreenManager() :
+  waiting_threads(),
+  running(),
+  speed(1.0), 
+  nextpop(false), 
+  nextpush(false), 
+  fps(0), 
+  next_screen(),
+  current_screen(),
+  console(),
+  screen_fade(),
+  screen_stack(),
+  screenshot_requested(false)
+{
+  using namespace Scripting;
+  TimeScheduler::instance = new TimeScheduler();
+}
+
+ScreenManager::~ScreenManager()
+{
+  using namespace Scripting;
+  delete TimeScheduler::instance;
+  TimeScheduler::instance = NULL;
+
+  for(std::vector<Screen*>::iterator i = screen_stack.begin();
+      i != screen_stack.end(); ++i) {
+    delete *i;
+  }
+}
+
+void
+ScreenManager::push_screen(Screen* screen, ScreenFade* screen_fade)
+{
+  this->next_screen.reset(screen);
+  this->screen_fade.reset(screen_fade);
+  nextpush = !nextpop;
+  nextpop = false;
+  speed = 1.0f;
+}
+
+void
+ScreenManager::exit_screen(ScreenFade* screen_fade)
+{
+  next_screen.reset(NULL);
+  this->screen_fade.reset(screen_fade);
+  nextpop = true;
+  nextpush = false;
+}
+
+void
+ScreenManager::set_screen_fade(ScreenFade* screen_fade)
+{
+  this->screen_fade.reset(screen_fade);
+}
+
+void
+ScreenManager::quit(ScreenFade* screen_fade)
+{
+  for(std::vector<Screen*>::iterator i = screen_stack.begin();
+      i != screen_stack.end(); ++i)
+    delete *i;
+  screen_stack.clear();
+
+  exit_screen(screen_fade);
+}
+
+void
+ScreenManager::set_speed(float speed)
+{
+  this->speed = speed;
+}
+
+float
+ScreenManager::get_speed() const
+{
+  return speed;
+}
+
+bool
+ScreenManager::has_no_pending_fadeout() const
+{
+  return screen_fade.get() == NULL || screen_fade->done();
+}
+
+void
+ScreenManager::draw_fps(DrawingContext& context, float fps_fps)
+{
+  char str[60];
+  snprintf(str, sizeof(str), "%3.1f", fps_fps);
+  const char* fpstext = "FPS";
+  context.draw_text(Resources::small_font, fpstext, 
+                    Vector(SCREEN_WIDTH - Resources::small_font->get_text_width(fpstext) - Resources::small_font->get_text_width(" 99999") - BORDER_X, 
+                           BORDER_Y + 20), ALIGN_LEFT, LAYER_HUD);
+  context.draw_text(Resources::small_font, str, Vector(SCREEN_WIDTH - BORDER_X, BORDER_Y + 20), ALIGN_RIGHT, LAYER_HUD);
+}
+
+void
+ScreenManager::draw(DrawingContext& context)
+{
+  static Uint32 fps_ticks = SDL_GetTicks();
+  static int frame_count = 0;
+
+  current_screen->draw(context);
+  if(MenuManager::current() != NULL)
+    MenuManager::current()->draw(context);
+  if(screen_fade.get() != NULL)
+    screen_fade->draw(context);
+  Console::instance->draw(context);
+
+  if(g_config->show_fps)
+    draw_fps(context, fps);
+
+  // if a screenshot was requested, pass request on to drawing_context
+  if (screenshot_requested) {
+    context.take_screenshot();
+    screenshot_requested = false;
+  }
+  context.do_drawing();
+
+  /* Calculate frames per second */
+  if(g_config->show_fps)
+  {
+    ++frame_count;
+
+    if(SDL_GetTicks() - fps_ticks >= 500)
+    {
+      fps = (float) frame_count / .5;
+      frame_count = 0;
+      fps_ticks = SDL_GetTicks();
+    }
+  }
+}
+
+void
+ScreenManager::update_gamelogic(float elapsed_time)
+{
+  Scripting::update_debugger();
+  Scripting::TimeScheduler::instance->update(game_time);
+  current_screen->update(elapsed_time);
+  if (MenuManager::current() != NULL)
+    MenuManager::current()->update();
+  if(screen_fade.get() != NULL)
+    screen_fade->update(elapsed_time);
+  Console::instance->update(elapsed_time);
+}
+
+void
+ScreenManager::process_events()
+{
+  g_main_controller->update();
+  Uint8* keystate = SDL_GetKeyState(NULL);
+  SDL_Event event;
+  while(SDL_PollEvent(&event)) 
+  {
+    g_main_controller->process_event(event);
+
+    if(MenuManager::current() != NULL)
+      MenuManager::current()->event(event);
+
+    switch(event.type)
+    {
+      case SDL_QUIT:
+        quit();
+        break;
+              
+      case SDL_VIDEORESIZE:
+        Renderer::instance()->resize(event.resize.w, event.resize.h);
+        MenuManager::recalc_pos();
+        break;
+            
+      case SDL_KEYDOWN:
+        if (event.key.keysym.sym == SDLK_F10)
+        {
+          g_config->show_fps = !g_config->show_fps;
+        }
+        if (event.key.keysym.sym == SDLK_F11) 
+        {
+          g_config->use_fullscreen = !g_config->use_fullscreen;
+          Renderer::instance()->apply_config();
+          MenuManager::recalc_pos();
+        }
+        else if (event.key.keysym.sym == SDLK_PRINT ||
+                 event.key.keysym.sym == SDLK_F12)
+        {
+          take_screenshot();
+        }
+        else if (event.key.keysym.sym == SDLK_F1 &&
+                 (keystate[SDLK_LCTRL] || keystate[SDLK_RCTRL]) &&
+                 keystate[SDLK_c])
+        {
+          Console::instance->toggle();
+          g_config->console_enabled = true;
+          g_config->save();
+        }
+        break;
+    }
+  }
+}
+
+void
+ScreenManager::handle_screen_switch()
+{
+  while( (next_screen.get() != NULL || nextpop) &&
+         has_no_pending_fadeout()) {
+    if(current_screen.get() != NULL) {
+      current_screen->leave();
+    }
+
+    if(nextpop) {
+      if(screen_stack.empty()) {
+        running = false;
+        break;
+      }
+      next_screen.reset(screen_stack.back());
+      screen_stack.pop_back();
+    }
+    if(nextpush && current_screen.get() != NULL) {
+      screen_stack.push_back(current_screen.release());
+    }
+
+    nextpush = false;
+    nextpop = false;
+    speed = 1.0;
+    Screen* next_screen_ptr = next_screen.release();
+    next_screen.reset(0);
+    if(next_screen_ptr)
+      next_screen_ptr->setup();
+    current_screen.reset(next_screen_ptr);
+    screen_fade.reset(NULL);
+
+    waiting_threads.wakeup();
+  }
+}
+
+void
+ScreenManager::run(DrawingContext &context)
+{
+  Uint32 last_ticks = 0;
+  Uint32 elapsed_ticks = 0;
+
+  running = true;
+  while(running) {
+
+    handle_screen_switch();
+    if(!running || current_screen.get() == NULL)
+      break;
+
+    Uint32 ticks = SDL_GetTicks();
+    elapsed_ticks += ticks - last_ticks;
+    last_ticks = ticks;
+
+    Uint32 ticks_per_frame = (Uint32) (TICKS_PER_FRAME * g_game_speed);
+
+    if (elapsed_ticks > ticks_per_frame*4) {
+      // when the game loads up or levels are switched the
+      // elapsed_ticks grows extremely large, so we just ignore those
+      // large time jumps
+      elapsed_ticks = 0;
+    }
+
+    if(elapsed_ticks < ticks_per_frame)
+    {
+      Uint32 delay_ticks = ticks_per_frame - elapsed_ticks;
+      SDL_Delay(delay_ticks);
+      last_ticks += delay_ticks;
+      elapsed_ticks += delay_ticks;
+    }
+
+    int frames = 0;
+
+    while(elapsed_ticks >= ticks_per_frame && frames < MAX_FRAME_SKIP) 
+    {
+      elapsed_ticks -= ticks_per_frame;
+      float timestep = 1.0 / LOGICAL_FPS;
+      real_time += timestep;
+      timestep *= speed;
+      game_time += timestep;
+
+      process_events();
+      update_gamelogic(timestep);
+      frames += 1;
+    }
+
+    draw(context);
+
+    sound_manager->update();
+  }
+}
+
+void 
+ScreenManager::take_screenshot()
+{
+  screenshot_requested = true;
+}
+
+/* EOF */
diff --git a/src/supertux/screen_manager.hpp b/src/supertux/screen_manager.hpp
new file mode 100644 (file)
index 0000000..09acd6a
--- /dev/null
@@ -0,0 +1,83 @@
+//  SuperTux
+//  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 as published by
+//  the Free Software Foundation, either version 3 of the License, or
+//  (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  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, see <http://www.gnu.org/licenses/>.
+
+#ifndef HEADER_SUPERTUX_SUPERTUX_MAINLOOP_HPP
+#define HEADER_SUPERTUX_SUPERTUX_MAINLOOP_HPP
+
+#include <memory>
+
+#include "scripting/thread_queue.hpp"
+
+class Screen;
+class Console;
+class ScreenFade;
+class DrawingContext;
+
+/**
+ * Manages, updates and draws all Screens, Controllers, Menus and the Console.
+ */
+class ScreenManager
+{
+public:
+  ScreenManager();
+  ~ScreenManager();
+
+  void run(DrawingContext &context);
+  void exit_screen(ScreenFade* fade = NULL);
+  void quit(ScreenFade* fade = NULL);
+  void set_speed(float speed);
+  float get_speed() const;
+  bool has_no_pending_fadeout() const;
+
+  /**
+   * requests that a screenshot be taken after the next frame has been rendered
+   */
+  void take_screenshot();
+
+  // push new screen on screen_stack
+  void push_screen(Screen* screen, ScreenFade* fade = NULL);
+  void set_screen_fade(ScreenFade* fade);
+
+  /// threads that wait for a screenswitch
+  Scripting::ThreadQueue waiting_threads;
+
+private:
+  void draw_fps(DrawingContext& context, float fps);
+  void draw(DrawingContext& context);
+  void update_gamelogic(float elapsed_time);
+  void process_events();
+  void handle_screen_switch();
+
+private:
+  bool running;
+  float speed;
+  bool nextpop;
+  bool nextpush;
+  /// measured fps
+  float fps;
+  std::auto_ptr<Screen> next_screen;
+  std::auto_ptr<Screen> current_screen;
+  std::auto_ptr<Console> console;
+  std::auto_ptr<ScreenFade> screen_fade;
+  std::vector<Screen*> screen_stack;
+  bool screenshot_requested; /**< true if a screenshot should be taken after the next frame has been rendered */
+};
+
+extern ScreenManager* g_screen_manager;
+
+#endif
+
+/* EOF */
index 48725fb..8d5db1a 100644 (file)
@@ -22,7 +22,7 @@
 #include "supertux/fadeout.hpp"
 #include "supertux/info_box_line.hpp"
 #include "supertux/globals.hpp"
-#include "supertux/mainloop.hpp"
+#include "supertux/screen_manager.hpp"
 #include "supertux/resources.hpp"
 #include "util/reader.hpp"
 #include "video/drawing_context.hpp"
@@ -102,7 +102,7 @@ TextScroller::update(float elapsed_time)
      || g_main_controller->pressed(Controller::MENU_SELECT))
     scroll += SCROLL;
   if(g_main_controller->pressed(Controller::PAUSE_MENU)) {
-    g_main_loop->exit_screen(new FadeOut(0.5));
+    g_screen_manager->exit_screen(new FadeOut(0.5));
   }
 
   scroll += speed * elapsed_time;
@@ -129,7 +129,7 @@ TextScroller::draw(DrawingContext& context)
 
   if(y < 0 && !fading ) {
     fading = true;
-    g_main_loop->exit_screen(new FadeOut(0.5));
+    g_screen_manager->exit_screen(new FadeOut(0.5));
   }
 }
 
index afbc717..df3ab3c 100644 (file)
 //  You should have received a copy of the GNU General Public License
 //  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-
 #include "supertux/title_screen.hpp"
 
-
 #include "audio/sound_manager.hpp"
 #include "gui/menu_manager.hpp"
 #include "lisp/parser.hpp"
@@ -27,7 +25,7 @@
 #include "supertux/fadeout.hpp"
 #include "supertux/gameconfig.hpp"
 #include "supertux/globals.hpp"
-#include "supertux/mainloop.hpp"
+#include "supertux/screen_manager.hpp"
 #include "supertux/menu/addon_menu.hpp"
 #include "supertux/menu/contrib_world_menu.hpp"
 #include "supertux/menu/contrib_menu.hpp"
@@ -189,7 +187,7 @@ TitleScreen::draw(DrawingContext& context)
 void
 TitleScreen::update(float elapsed_time)
 {
-  g_main_loop->set_speed(0.6f);
+  g_screen_manager->set_speed(0.6f);
   Sector* sector  = titlesession->get_current_sector();
   sector->update(elapsed_time);
 
@@ -223,12 +221,12 @@ TitleScreen::update(float elapsed_time)
 
         case MNID_CREDITS:
           MenuManager::set_current(NULL);
-          g_main_loop->push_screen(new TextScroller("credits.txt"),
+          g_screen_manager->push_screen(new TextScroller("credits.txt"),
                                    new FadeOut(0.5));
           break;
 
         case MNID_QUITMAINMENU:
-          g_main_loop->quit(new FadeOut(0.25));
+          g_screen_manager->quit(new FadeOut(0.25));
           sound_manager->stop_music(0.25);
           break;
       }
@@ -243,7 +241,7 @@ TitleScreen::update(float elapsed_time)
 
   // reopen menu if user closed it (so that the app doesn't close when user
   // accidently hit ESC)
-  if(MenuManager::current() == 0 && g_main_loop->has_no_pending_fadeout()) {
+  if(MenuManager::current() == 0 && g_screen_manager->has_no_pending_fadeout()) {
     generate_main_menu();
     MenuManager::set_current(main_menu.get());
   }
index a8fda6b..07de751 100644 (file)
@@ -19,7 +19,7 @@
 #include "physfs/ifile_stream.hpp"
 #include "scripting/serialize.hpp"
 #include "scripting/squirrel_util.hpp"
-#include "supertux/mainloop.hpp"
+#include "supertux/screen_manager.hpp"
 #include "supertux/player_status.hpp"
 #include "supertux/world.hpp"
 #include "util/file_system.hpp"
@@ -151,7 +151,7 @@ World::run()
   } catch(std::exception& ) {
     // fallback: try to load worldmap worldmap.stwm
     using namespace WorldMapNS;
-    g_main_loop->push_screen(new WorldMap(basedir + "worldmap.stwm"));
+    g_screen_manager->push_screen(new WorldMap(basedir + "worldmap.stwm"));
   }
 }