From: grumbel Date: Thu, 19 Nov 2009 16:50:58 +0000 (+0000) Subject: Renamed MainLoop to ScreenManager X-Git-Url: https://git.verplant.org/?a=commitdiff_plain;h=0c8a4a23f06aaa461d51c0ba21e5db5cd3427d8a;p=supertux.git Renamed MainLoop to ScreenManager git-svn-id: http://supertux.lethargik.org/svn/supertux/trunk/supertux@6050 837edb03-e0f3-0310-88ca-d4d4e8b29345 --- diff --git a/src/supertux/game_session.cpp b/src/supertux/game_session.cpp index 001b5e7ed..94eedd53b 100644 --- a/src/supertux/game_session.cpp +++ b/src/supertux/game_session.cpp @@ -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(); diff --git a/src/supertux/levelintro.cpp b/src/supertux/levelintro.cpp index 821699576..f7cb7d8da 100644 --- a/src/supertux/levelintro.cpp +++ b/src/supertux/levelintro.cpp @@ -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; diff --git a/src/supertux/main.cpp b/src/supertux/main.cpp index 10744f3a3..0314797eb 100644 --- a/src/supertux/main.cpp +++ b/src/supertux/main.cpp @@ -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 index c5ac1f64d..000000000 --- a/src/supertux/mainloop.cpp +++ /dev/null @@ -1,342 +0,0 @@ -// SuperTux -// Copyright (C) 2006 Matthias Braun -// -// 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 . - -#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::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::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 index 7f7b78fe4..000000000 --- a/src/supertux/mainloop.hpp +++ /dev/null @@ -1,83 +0,0 @@ -// SuperTux -// Copyright (C) 2006 Matthias Braun -// -// 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 . - -#ifndef HEADER_SUPERTUX_SUPERTUX_MAINLOOP_HPP -#define HEADER_SUPERTUX_SUPERTUX_MAINLOOP_HPP - -#include - -#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 next_screen; - std::auto_ptr current_screen; - std::auto_ptr console; - std::auto_ptr screen_fade; - std::vector 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 */ diff --git a/src/supertux/menu/contrib_world_menu.cpp b/src/supertux/menu/contrib_world_menu.cpp index fdb84c589..b3e0fe116 100644 --- a/src/supertux/menu/contrib_world_menu.cpp +++ b/src/supertux/menu/contrib_world_menu.cpp @@ -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 index 000000000..2b4478ecc --- /dev/null +++ b/src/supertux/screen_manager.cpp @@ -0,0 +1,342 @@ +// SuperTux +// Copyright (C) 2006 Matthias Braun +// +// 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 . + +#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::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::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 index 000000000..09acd6afd --- /dev/null +++ b/src/supertux/screen_manager.hpp @@ -0,0 +1,83 @@ +// SuperTux +// Copyright (C) 2006 Matthias Braun +// +// 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 . + +#ifndef HEADER_SUPERTUX_SUPERTUX_MAINLOOP_HPP +#define HEADER_SUPERTUX_SUPERTUX_MAINLOOP_HPP + +#include + +#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 next_screen; + std::auto_ptr current_screen; + std::auto_ptr console; + std::auto_ptr screen_fade; + std::vector 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 */ diff --git a/src/supertux/textscroller.cpp b/src/supertux/textscroller.cpp index 48725fb7c..8d5db1ace 100644 --- a/src/supertux/textscroller.cpp +++ b/src/supertux/textscroller.cpp @@ -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)); } } diff --git a/src/supertux/title_screen.cpp b/src/supertux/title_screen.cpp index afbc71730..df3ab3ccf 100644 --- a/src/supertux/title_screen.cpp +++ b/src/supertux/title_screen.cpp @@ -15,10 +15,8 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . - #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()); } diff --git a/src/supertux/world.cpp b/src/supertux/world.cpp index a8fda6ba7..07de751ba 100644 --- a/src/supertux/world.cpp +++ b/src/supertux/world.cpp @@ -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")); } }