00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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
00156 if (screenshot_requested) {
00157 context.take_screenshot();
00158 screenshot_requested = false;
00159 }
00160 context.do_drawing();
00161
00162
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
00298
00299
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