X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=src%2Fgameloop.cpp;h=790b8afdb0d9a510addb5abc6fe53e1a44928ffe;hb=ff8e7dfe9011afc8bdd4ca29b6a6306737d75689;hp=d42c2052297cbc7e1fe501840909301b402ec0e2;hpb=b8c83bae1b0cd0367b6e3ac8c4c28e077eb1b594;p=supertux.git diff --git a/src/gameloop.cpp b/src/gameloop.cpp index d42c20522..790b8afdb 100644 --- a/src/gameloop.cpp +++ b/src/gameloop.cpp @@ -20,16 +20,16 @@ // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include #include -#include -#include -#include +#include + +#include "SDL.h" #ifndef WIN32 #include @@ -39,12 +39,12 @@ #include "defines.h" #include "globals.h" #include "gameloop.h" -#include "screen.h" +#include "screen/screen.h" #include "setup.h" #include "high_scores.h" #include "menu.h" #include "badguy.h" -#include "world.h" +#include "sector.h" #include "special.h" #include "player.h" #include "level.h" @@ -54,13 +54,14 @@ #include "particlesystem.h" #include "resources.h" #include "background.h" -#include "music_manager.h" +#include "tilemap.h" +#include "gettext.h" GameSession* GameSession::current_ = 0; -GameSession::GameSession(const std::string& subset_, int levelnb_, int mode) - : world(0), st_gl_mode(mode), levelnb(levelnb_), end_sequence(NO_ENDSEQUENCE), - subset(subset_) +GameSession::GameSession(const std::string& levelname_, int mode) + : level(0), currentsector(0), st_gl_mode(mode), + end_sequence(NO_ENDSEQUENCE), levelname(levelname_) { current_ = this; @@ -71,6 +72,8 @@ GameSession::GameSession(const std::string& subset_, int levelnb_, int mode) fps_timer.init(true); frame_timer.init(true); + context = new DrawingContext(); + restart_level(); } @@ -84,28 +87,25 @@ GameSession::restart_level() fps_timer.init(true); frame_timer.init(true); +#if 0 float old_x_pos = -1; - if (world) { // Tux has lost a life, so we try to respawn him at the nearest reset point old_x_pos = world->get_tux()->base.x; } +#endif - delete world; + delete level; + currentsector = 0; - if (st_gl_mode == ST_GL_LOAD_LEVEL_FILE) - { - world = new World(subset); - } - else if (st_gl_mode == ST_GL_DEMO_GAME) - { - world = new World(subset); - } - else - { - world = new World(subset, levelnb); - } + level = new Level; + level->load(levelname); + currentsector = level->get_sector("main"); + if(!currentsector) + st_abort("Level has no main sector.", ""); + currentsector->activate("main"); +#if 0 // TODO // Set Tux to the nearest reset point if (old_x_pos != -1) { @@ -123,6 +123,7 @@ GameSession::restart_level() world->get_tux()->base.y = best_reset_point.y; } } +#endif if (st_gl_mode != ST_GL_DEMO_GAME) { @@ -132,35 +133,37 @@ GameSession::restart_level() time_left.init(true); start_timers(); - world->play_music(LEVEL_MUSIC); + currentsector->play_music(LEVEL_MUSIC); } GameSession::~GameSession() { - delete world; + delete level; + delete context; } void GameSession::levelintro(void) { - music_manager->halt_music(); + sound_manager->halt_music(); char str[60]; - Camera dummy; - world->background->draw(dummy, LAYER_BACKGROUND0); + DrawingContext context; + currentsector->background->draw(context); - sprintf(str, "%s", world->get_level()->name.c_str()); - gold_text->drawf(str, 0, 220, A_HMIDDLE, A_TOP, 1); + context.draw_text_center(gold_text, level->get_name(), Vector(0, 220), + LAYER_FOREGROUND1); sprintf(str, "TUX x %d", player_status.lives); - white_text->drawf(str, 0, 240, A_HMIDDLE, A_TOP, 1); - - sprintf(str, "by %s", world->get_level()->author.c_str()); - white_small_text->drawf(str, 0, 400, A_HMIDDLE, A_TOP, 1); + context.draw_text_center(white_text, str, Vector(0, 240), + LAYER_FOREGROUND1); + context.draw_text_center(white_small_text, + std::string(_("by ")) + level->get_author(), + Vector(0, 400), LAYER_FOREGROUND1); - flipscreen(); + context.do_drawing(); SDL_Event event; wait_for_event(event,1000,3000,true); @@ -170,7 +173,7 @@ GameSession::levelintro(void) void GameSession::start_timers() { - time_left.start(world->get_level()->time_left*1000); + time_left.start(level->time_left*1000); st_pause_ticks_init(); update_time = st_get_ticks(); } @@ -178,8 +181,9 @@ GameSession::start_timers() void GameSession::on_escape_press() { - if(world->get_tux()->dying || end_sequence != NO_ENDSEQUENCE) + if(currentsector->player->dying || end_sequence != NO_ENDSEQUENCE) return; // don't let the player open the menu, when he is dying + if(game_pause) return; @@ -192,7 +196,7 @@ GameSession::on_escape_press() /* Tell Tux that the keys are all down, otherwise it could have nasty bugs, like going allways to the right or whatever that key does */ - Player& tux = *world->get_tux(); + Player& tux = *(currentsector->player); tux.key_event((SDLKey)keymap.jump, UP); tux.key_event((SDLKey)keymap.duck, UP); tux.key_event((SDLKey)keymap.left, UP); @@ -209,7 +213,7 @@ GameSession::process_events() { if (end_sequence != NO_ENDSEQUENCE) { - Player& tux = *world->get_tux(); + Player& tux = *currentsector->player; tux.input.fire = UP; tux.input.left = UP; @@ -278,7 +282,7 @@ GameSession::process_events() } else { - Player& tux = *world->get_tux(); + Player& tux = *currentsector->player; switch(event.type) { @@ -312,6 +316,19 @@ GameSession::process_events() switch(key) { + case SDLK_a: + if(debug_mode) + { + char buf[160]; + snprintf(buf, sizeof(buf), "P: %4.1f,%4.1f", + tux.base.x, tux.base.y); + context->draw_text(white_text, buf, + Vector(0, screen->h - white_text->get_height()), + LAYER_FOREGROUND1); + context->do_drawing(); + SDL_Delay(1000); + } + break; case SDLK_p: if(!Menu::current()) { @@ -330,13 +347,7 @@ GameSession::process_events() case SDLK_TAB: if(debug_mode) { - tux.size = !tux.size; - if(tux.size == BIG) - { - tux.base.height = 64; - } - else - tux.base.height = 32; + tux.grow(false); } break; case SDLK_END: @@ -430,22 +441,12 @@ GameSession::process_events() void GameSession::check_end_conditions() { - Player* tux = world->get_tux(); + Player* tux = currentsector->player; /* End of level? */ - int endpos = (World::current()->get_level()->width-5) * 32; Tile* endtile = collision_goal(tux->base); - // fallback in case the other endpositions don't trigger - if (!end_sequence && tux->base.x >= endpos) - { - end_sequence = ENDSEQUENCE_WAITING; - last_x_pos = -1; - music_manager->play_music(level_end_song, 0); - endsequence_timer.start(7000); - tux->invincible_timer.start(7000); //FIXME: Implement a winning timer for the end sequence (with special winning animation etc.) - } - else if(end_sequence && !endsequence_timer.check()) + if(end_sequence && !endsequence_timer.check()) { exit_status = ES_LEVEL_FINISHED; return; @@ -458,7 +459,7 @@ GameSession::check_end_conditions() { end_sequence = ENDSEQUENCE_RUNNING; last_x_pos = -1; - music_manager->play_music(level_end_song, 0); + sound_manager->play_music(level_end_song, 0); endsequence_timer.start(7000); // 5 seconds until we finish the map tux->invincible_timer.start(7000); //FIXME: Implement a winning timer for the end sequence (with special winning animation etc.) } @@ -482,37 +483,54 @@ GameSession::check_end_conditions() void GameSession::action(double frame_ratio) { - if (exit_status == ES_NONE) + if (exit_status == ES_NONE && !currentsector->player->growing_timer.check()) { // Update Tux and the World - world->action(frame_ratio); + currentsector->action(frame_ratio); } + + // respawning in new sector? + if(newsector != "" && newspawnpoint != "") { + Sector* sector = level->get_sector(newsector); + currentsector = sector; + currentsector->activate(newspawnpoint); + currentsector->play_music(LEVEL_MUSIC); + newsector = newspawnpoint = ""; + } } void GameSession::draw() { - world->draw(); - drawstatus(); + currentsector->draw(*context); + drawstatus(*context); if(game_pause) { int x = screen->h / 20; for(int i = 0; i < x; ++i) { - fillrect(i % 2 ? (pause_menu_frame * i)%screen->w : -((pause_menu_frame * i)%screen->w) ,(i*20+pause_menu_frame)%screen->h,screen->w,10,20,20,20, rand() % 20 + 1); + context->draw_filled_rect( + Vector(i % 2 ? (pause_menu_frame * i)%screen->w : + -((pause_menu_frame * i)%screen->w) + ,(i*20+pause_menu_frame)%screen->h), + Vector(screen->w,10), + Color(20,20,20, rand() % 20 + 1), LAYER_FOREGROUND1+1); } - fillrect(0,0,screen->w,screen->h,rand() % 50, rand() % 50, rand() % 50, 128); - blue_text->drawf("PAUSE - Press 'P' To Play", 0, 230, A_HMIDDLE, A_TOP, 1); + context->draw_filled_rect( + Vector(0,0), Vector(screen->w, screen->h), + Color(rand() % 50, rand() % 50, rand() % 50, 128), LAYER_FOREGROUND1); + context->draw_text_center(blue_text, _("PAUSE - Press 'P' To Play"), + Vector(0, 230), LAYER_FOREGROUND1+2); } if(Menu::current()) { - Menu::current()->draw(); - mouse_cursor->draw(); + Menu::current()->draw(*context); + mouse_cursor->draw(*context); } - updatescreen(); + context->do_drawing(); } void @@ -575,7 +593,8 @@ GameSession::run() } /* Handle events: */ - world->get_tux()->input.old_fire = world->get_tux()->input.fire; + currentsector->player->input.old_fire + = currentsector->player->input.fire; process_events(); process_menu(); @@ -620,24 +639,24 @@ GameSession::run() } /* Handle time: */ - if (!time_left.check() && world->get_tux()->dying == DYING_NOT + if (!time_left.check() && currentsector->player->dying == DYING_NOT && !end_sequence) - world->get_tux()->kill(Player::KILL); + currentsector->player->kill(Player::KILL); /* Handle music: */ - if(world->get_tux()->invincible_timer.check() && !end_sequence) + if(currentsector->player->invincible_timer.check() && !end_sequence) { - world->play_music(HERRING_MUSIC); + currentsector->play_music(HERRING_MUSIC); } /* are we low on time ? */ else if (time_left.get_left() < TIME_WARNING && !end_sequence) { - world->play_music(HURRYUP_MUSIC); + currentsector->play_music(HURRYUP_MUSIC); } /* or just normal music? */ - else if(world->get_music_type() != LEVEL_MUSIC && !end_sequence) + else if(currentsector->get_music_type() != LEVEL_MUSIC && !end_sequence) { - world->play_music(LEVEL_MUSIC); + currentsector->play_music(LEVEL_MUSIC); } /* Calculate frames per second */ @@ -657,60 +676,92 @@ GameSession::run() return exit_status; } +void +GameSession::respawn(const std::string& sector, const std::string& spawnpoint) +{ + newsector = sector; + newspawnpoint = spawnpoint; +} + /* Bounce a brick: */ void bumpbrick(float x, float y) { - World::current()->add_bouncy_brick(Vector(((int)(x + 1) / 32) * 32, + Sector::current()->add_bouncy_brick(Vector(((int)(x + 1) / 32) * 32, (int)(y / 32) * 32)); - play_sound(sounds[SND_BRICK], SOUND_CENTER_SPEAKER); + sound_manager->play_sound(sounds[SND_BRICK], Vector(x, y)); } /* (Status): */ void -GameSession::drawstatus() +GameSession::drawstatus(DrawingContext& context) { char str[60]; - - snprintf(str, 60, "%d", player_status.score); - white_text->draw("SCORE", 0, 0, 1); - gold_text->draw(str, 96, 0, 1); + + snprintf(str, 60, " %d", player_status.score); + context.draw_text(white_text, _("SCORE"), Vector(0, 0), LAYER_FOREGROUND1); + context.draw_text(gold_text, str, Vector(96, 0), LAYER_FOREGROUND1); if(st_gl_mode == ST_GL_TEST) { - white_text->draw("Press ESC To Return",0,20,1); + context.draw_text(white_text, _("Press ESC To Return"), Vector(0,20), + LAYER_FOREGROUND1); } if(!time_left.check()) { - white_text->draw("TIME'S UP", screen->w/2 - white_text->w*8, 0, 1); + context.draw_text_center(white_text, _("TIME's UP"), Vector(0, 0), + LAYER_FOREGROUND1); } else if (time_left.get_left() > TIME_WARNING || (global_frame_counter % 10) < 5) { - sprintf(str, "%d", time_left.get_left() / 1000 ); - white_text->draw("TIME", screen->w/2 - white_text->w*4, 0, 1); - gold_text->draw(str, screen->w/2 + gold_text->w, 0, 1); + sprintf(str, " %d", time_left.get_left() / 1000 ); + context.draw_text_center(white_text, _("TIME"), + Vector(0, 0), LAYER_FOREGROUND1); + context.draw_text_center(gold_text, str, + Vector(4*16, 0), LAYER_FOREGROUND1); } - sprintf(str, "%d", player_status.distros); - white_text->draw("COINS", screen->w - white_text->w*9, 0, 1); - gold_text->draw(str, screen->w - gold_text->w*2, 0, 1); + sprintf(str, " %d", player_status.distros); + context.draw_text(white_text, _("COINS"), + Vector(screen->w - white_text->get_text_width(_("COINS"))-white_text->get_text_width(" 99"), 0), + LAYER_FOREGROUND1); + context.draw_text(gold_text, str, + Vector(screen->w - gold_text->get_text_width(" 99"), 0),LAYER_FOREGROUND1); - white_text->draw("LIVES", screen->w - white_text->w*9, 20); if (player_status.lives >= 5) { sprintf(str, "%dx", player_status.lives); - gold_text->draw_align(str, screen->w - gold_text->w, 20, A_RIGHT, A_TOP); - tux_life->draw(screen->w - gold_text->w, 20); + float x = screen->w - gold_text->get_text_width(str) - tux_life->w; + context.draw_text(gold_text, str, Vector(x, 20), LAYER_FOREGROUND1); + context.draw_surface(tux_life, Vector(screen->w - 16, 20), + LAYER_FOREGROUND1); } else { for(int i= 0; i < player_status.lives; ++i) - tux_life->draw(screen->w - tux_life->w*4 +(tux_life->w*i), 20); + context.draw_surface(tux_life, + Vector(screen->w - tux_life->w*4 +(tux_life->w*i), 20), + LAYER_FOREGROUND1); + } + + context.draw_text(white_text, _("LIVES"), + Vector(screen->w - white_text->get_text_width(_("LIVES")) - white_text->get_text_width(" 99"), 20), + LAYER_FOREGROUND1); + + if(game_pause) + { + sprintf(str, _("Playing: %s"), level->name.c_str()); + + context.draw_text(white_text, str, Vector(0,20), + LAYER_FOREGROUND1); } if(show_fps) { sprintf(str, "%2.1f", fps_fps); - white_text->draw("FPS", screen->w - white_text->w*9, 40, 1); - gold_text->draw_align(str, screen->w, 40, A_RIGHT, A_TOP); + context.draw_text(white_text, "FPS", + Vector(screen->w - white_text->get_text_width("FPS "), 40), + LAYER_FOREGROUND1); + context.draw_text(gold_text, str, + Vector(screen->w-4*16, 40), LAYER_FOREGROUND1); } } @@ -719,18 +770,19 @@ GameSession::drawresultscreen(void) { char str[80]; - Camera dummy; - world->background->draw(dummy, LAYER_BACKGROUND0); + DrawingContext context; + currentsector->background->draw(context); - blue_text->drawf("Result:", 0, 200, A_HMIDDLE, A_TOP, 1); + context.draw_text_center(blue_text, _("Result:"), Vector(0, 200), + LAYER_FOREGROUND1); - sprintf(str, "SCORE: %d", player_status.score); - gold_text->drawf(str, 0, 224, A_HMIDDLE, A_TOP, 1); + sprintf(str, _("SCORE: %d"), player_status.score); + context.draw_text_center(gold_text, str, Vector(0, 224), LAYER_FOREGROUND1); - sprintf(str, "COINS: %d", player_status.distros); - gold_text->drawf(str, 0, 256, A_HMIDDLE, A_TOP, 1); + sprintf(str, _("COINS: %d"), player_status.distros); + context.draw_text_center(gold_text, str, Vector(0, 256), LAYER_FOREGROUND1); - flipscreen(); + context.do_drawing(); SDL_Event event; wait_for_event(event,2000,5000,true); @@ -747,7 +799,7 @@ std::string slotinfo(int slot) if (savegame) { LispReader reader(lisp_cdr(savegame)); - reader.read_string("title", &title); + reader.read_string("title", title); lisp_free(savegame); } @@ -756,10 +808,10 @@ std::string slotinfo(int slot) if (!title.empty()) snprintf(tmp,1024,"Slot %d - %s",slot, title.c_str()); else - snprintf(tmp, 1024,"Slot %d - Savegame",slot); + snprintf(tmp, 1024,_("Slot %d - Savegame"),slot); } else - sprintf(tmp,"Slot %d - Free",slot); + sprintf(tmp,_("Slot %d - Free"),slot); return tmp; }