src/supertux/screen_manager.cpp

Go to the documentation of this file.
00001 //  SuperTux
00002 //  Copyright (C) 2006 Matthias Braun <matze@braunis.de>
00003 //
00004 //  This program is free software: you can redistribute it and/or modify
00005 //  it under the terms of the GNU General Public License as published by
00006 //  the Free Software Foundation, either version 3 of the License, or
00007 //  (at your option) any later version.
00008 //
00009 //  This program is distributed in the hope that it will be useful,
00010 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 //  GNU General Public License for more details.
00013 //
00014 //  You should have received a copy of the GNU General Public License
00015 //  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00016 
00017 #include "supertux/screen_manager.hpp"
00018 
00019 #include "audio/sound_manager.hpp"
00020 #include "control/joystickkeyboardcontroller.hpp"
00021 #include "gui/menu.hpp"
00022 #include "gui/menu_manager.hpp"
00023 #include "scripting/squirrel_util.hpp"
00024 #include "scripting/time_scheduler.hpp"
00025 #include "supertux/constants.hpp"
00026 #include "supertux/console.hpp"
00027 #include "supertux/gameconfig.hpp"
00028 #include "supertux/globals.hpp"
00029 #include "supertux/main.hpp"
00030 #include "supertux/player_status.hpp"
00031 #include "supertux/resources.hpp"
00032 #include "supertux/screen_fade.hpp"
00033 #include "supertux/screen.hpp"
00034 #include "supertux/timer.hpp"
00035 #include "video/drawing_context.hpp"
00036 #include "video/renderer.hpp"
00037 
00039 static const Uint32 TICKS_PER_FRAME = (Uint32) (1000.0 / LOGICAL_FPS);
00041 static const int MAX_FRAME_SKIP = 2;
00042 
00043 ScreenManager::ScreenManager() :
00044   waiting_threads(),
00045   running(),
00046   speed(1.0), 
00047   nextpop(false), 
00048   nextpush(false), 
00049   fps(0), 
00050   next_screen(),
00051   current_screen(),
00052   console(),
00053   screen_fade(),
00054   screen_stack(),
00055   screenshot_requested(false)
00056 {
00057   using namespace scripting;
00058   TimeScheduler::instance = new TimeScheduler();
00059 }
00060 
00061 ScreenManager::~ScreenManager()
00062 {
00063   using namespace scripting;
00064   delete TimeScheduler::instance;
00065   TimeScheduler::instance = NULL;
00066 
00067   for(std::vector<Screen*>::iterator i = screen_stack.begin();
00068       i != screen_stack.end(); ++i) {
00069     delete *i;
00070   }
00071 }
00072 
00073 void
00074 ScreenManager::push_screen(Screen* screen, ScreenFade* screen_fade)
00075 {
00076   this->next_screen.reset(screen);
00077   this->screen_fade.reset(screen_fade);
00078   nextpush = !nextpop;
00079   nextpop = false;
00080   speed = 1.0f;
00081 }
00082 
00083 void
00084 ScreenManager::exit_screen(ScreenFade* screen_fade)
00085 {
00086   next_screen.reset(NULL);
00087   this->screen_fade.reset(screen_fade);
00088   nextpop = true;
00089   nextpush = false;
00090 }
00091 
00092 void
00093 ScreenManager::set_screen_fade(ScreenFade* screen_fade)
00094 {
00095   this->screen_fade.reset(screen_fade);
00096 }
00097 
00098 void
00099 ScreenManager::quit(ScreenFade* screen_fade)
00100 {
00101   for(std::vector<Screen*>::iterator i = screen_stack.begin();
00102       i != screen_stack.end(); ++i)
00103     delete *i;
00104   screen_stack.clear();
00105 
00106   exit_screen(screen_fade);
00107 }
00108 
00109 void
00110 ScreenManager::set_speed(float speed)
00111 {
00112   this->speed = speed;
00113 }
00114 
00115 float
00116 ScreenManager::get_speed() const
00117 {
00118   return speed;
00119 }
00120 
00121 bool
00122 ScreenManager::has_no_pending_fadeout() const
00123 {
00124   return screen_fade.get() == NULL || screen_fade->done();
00125 }
00126 
00127 void
00128 ScreenManager::draw_fps(DrawingContext& context, float fps_fps)
00129 {
00130   char str[60];
00131   snprintf(str, sizeof(str), "%3.1f", fps_fps);
00132   const char* fpstext = "FPS";
00133   context.draw_text(Resources::small_font, fpstext, 
00134                     Vector(SCREEN_WIDTH - Resources::small_font->get_text_width(fpstext) - Resources::small_font->get_text_width(" 99999") - BORDER_X, 
00135                            BORDER_Y + 20), ALIGN_LEFT, LAYER_HUD);
00136   context.draw_text(Resources::small_font, str, Vector(SCREEN_WIDTH - BORDER_X, BORDER_Y + 20), ALIGN_RIGHT, LAYER_HUD);
00137 }
00138 
00139 void
00140 ScreenManager::draw(DrawingContext& context)
00141 {
00142   static Uint32 fps_ticks = SDL_GetTicks();
00143   static int frame_count = 0;
00144 
00145   current_screen->draw(context);
00146   if(MenuManager::current() != NULL)
00147     MenuManager::current()->draw(context);
00148   if(screen_fade.get() != NULL)
00149     screen_fade->draw(context);
00150   Console::instance->draw(context);
00151 
00152   if(g_config->show_fps)
00153     draw_fps(context, fps);
00154 
00155   // if a screenshot was requested, pass request on to drawing_context
00156   if (screenshot_requested) {
00157     context.take_screenshot();
00158     screenshot_requested = false;
00159   }
00160   context.do_drawing();
00161 
00162   /* Calculate frames per second */
00163   if(g_config->show_fps)
00164   {
00165     ++frame_count;
00166 
00167     if(SDL_GetTicks() - fps_ticks >= 500)
00168     {
00169       fps = (float) frame_count / .5;
00170       frame_count = 0;
00171       fps_ticks = SDL_GetTicks();
00172     }
00173   }
00174 }
00175 
00176 void
00177 ScreenManager::update_gamelogic(float elapsed_time)
00178 {
00179   scripting::update_debugger();
00180   scripting::TimeScheduler::instance->update(game_time);
00181   current_screen->update(elapsed_time);
00182   if (MenuManager::current() != NULL)
00183     MenuManager::current()->update();
00184   if(screen_fade.get() != NULL)
00185     screen_fade->update(elapsed_time);
00186   Console::instance->update(elapsed_time);
00187 }
00188 
00189 void
00190 ScreenManager::process_events()
00191 {
00192   g_jk_controller->update();
00193   Uint8* keystate = SDL_GetKeyState(NULL);
00194   SDL_Event event;
00195   while(SDL_PollEvent(&event)) 
00196   {
00197     g_jk_controller->process_event(event);
00198 
00199     if(MenuManager::current() != NULL)
00200       MenuManager::current()->event(event);
00201 
00202     switch(event.type)
00203     {
00204       case SDL_QUIT:
00205         quit();
00206         break;
00207               
00208       case SDL_VIDEORESIZE:
00209         Renderer::instance()->resize(event.resize.w, event.resize.h);
00210         MenuManager::recalc_pos();
00211         break;
00212             
00213       case SDL_KEYDOWN:
00214         if (event.key.keysym.sym == SDLK_F10)
00215         {
00216           g_config->show_fps = !g_config->show_fps;
00217         }
00218         if (event.key.keysym.sym == SDLK_F11) 
00219         {
00220           g_config->use_fullscreen = !g_config->use_fullscreen;
00221           Renderer::instance()->apply_config();
00222           MenuManager::recalc_pos();
00223         }
00224         else if (event.key.keysym.sym == SDLK_PRINT ||
00225                  event.key.keysym.sym == SDLK_F12)
00226         {
00227           take_screenshot();
00228         }
00229         else if (event.key.keysym.sym == SDLK_F1 &&
00230                  (keystate[SDLK_LCTRL] || keystate[SDLK_RCTRL]) &&
00231                  keystate[SDLK_c])
00232         {
00233           Console::instance->toggle();
00234           g_config->console_enabled = true;
00235           g_config->save();
00236         }
00237         break;
00238     }
00239   }
00240 }
00241 
00242 void
00243 ScreenManager::handle_screen_switch()
00244 {
00245   while( (next_screen.get() != NULL || nextpop) &&
00246          has_no_pending_fadeout()) {
00247     if(current_screen.get() != NULL) {
00248       current_screen->leave();
00249     }
00250 
00251     if(nextpop) {
00252       if(screen_stack.empty()) {
00253         running = false;
00254         break;
00255       }
00256       next_screen.reset(screen_stack.back());
00257       screen_stack.pop_back();
00258     }
00259     if(nextpush && current_screen.get() != NULL) {
00260       screen_stack.push_back(current_screen.release());
00261     }
00262 
00263     nextpush = false;
00264     nextpop = false;
00265     speed = 1.0;
00266     Screen* next_screen_ptr = next_screen.release();
00267     next_screen.reset(0);
00268     if(next_screen_ptr)
00269       next_screen_ptr->setup();
00270     current_screen.reset(next_screen_ptr);
00271     screen_fade.reset(NULL);
00272 
00273     waiting_threads.wakeup();
00274   }
00275 }
00276 
00277 void
00278 ScreenManager::run(DrawingContext &context)
00279 {
00280   Uint32 last_ticks = 0;
00281   Uint32 elapsed_ticks = 0;
00282 
00283   running = true;
00284   while(running) {
00285 
00286     handle_screen_switch();
00287     if(!running || current_screen.get() == NULL)
00288       break;
00289 
00290     Uint32 ticks = SDL_GetTicks();
00291     elapsed_ticks += ticks - last_ticks;
00292     last_ticks = ticks;
00293 
00294     Uint32 ticks_per_frame = (Uint32) (TICKS_PER_FRAME * g_game_speed);
00295 
00296     if (elapsed_ticks > ticks_per_frame*4) {
00297       // when the game loads up or levels are switched the
00298       // elapsed_ticks grows extremely large, so we just ignore those
00299       // large time jumps
00300       elapsed_ticks = 0;
00301     }
00302 
00303     if(elapsed_ticks < ticks_per_frame)
00304     {
00305       Uint32 delay_ticks = ticks_per_frame - elapsed_ticks;
00306       SDL_Delay(delay_ticks);
00307       last_ticks += delay_ticks;
00308       elapsed_ticks += delay_ticks;
00309     }
00310 
00311     int frames = 0;
00312 
00313     while(elapsed_ticks >= ticks_per_frame && frames < MAX_FRAME_SKIP) 
00314     {
00315       elapsed_ticks -= ticks_per_frame;
00316       float timestep = 1.0 / LOGICAL_FPS;
00317       real_time += timestep;
00318       timestep *= speed;
00319       game_time += timestep;
00320 
00321       process_events();
00322       update_gamelogic(timestep);
00323       frames += 1;
00324     }
00325 
00326     draw(context);
00327 
00328     sound_manager->update();
00329   }
00330 }
00331 
00332 void 
00333 ScreenManager::take_screenshot()
00334 {
00335   screenshot_requested = true;
00336 }
00337 
00338 /* EOF */

Generated on Mon Jun 9 03:38:23 2014 for SuperTux by  doxygen 1.5.1