X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fgameloop.cpp;h=d05379f9dd3d760b87592cf88059d714dbe46798;hb=60cdeda6e1346430425b175674112c04450f4359;hp=251dafdcd2fa9bfa2484874073e261f158c243e8;hpb=e776775f2ef6a3843cb83b39b34980d98e208f2f;p=supertux.git diff --git a/src/gameloop.cpp b/src/gameloop.cpp index 251dafdcd..d05379f9d 100644 --- a/src/gameloop.cpp +++ b/src/gameloop.cpp @@ -20,16 +20,17 @@ // 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 + +#include "SDL.h" #ifndef WIN32 #include @@ -37,14 +38,14 @@ #endif #include "defines.h" -#include "globals.h" +#include "app/globals.h" #include "gameloop.h" -#include "screen.h" -#include "setup.h" +#include "video/screen.h" +#include "app/setup.h" #include "high_scores.h" -#include "menu.h" +#include "gui/menu.h" #include "badguy.h" -#include "world.h" +#include "sector.h" #include "special.h" #include "player.h" #include "level.h" @@ -53,21 +54,53 @@ #include "tile.h" #include "particlesystem.h" #include "resources.h" -#include "music_manager.h" +#include "background.h" +#include "tilemap.h" +#include "app/gettext.h" +#include "worldmap.h" +#include "intro.h" +#include "misc.h" +#include "camera.h" +#include "statistics.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_) +bool compare_last(std::string& haystack, std::string needle) +{ +int haystack_size = haystack.size(); +int needle_size = needle.size(); + +if(haystack_size < needle_size) + return false; + +if(haystack.compare(haystack_size-needle_size, needle_size, needle) == 0) + return true; +return false; +} + +GameSession::GameSession(const std::string& levelname_, int mode, bool flip_level_, Statistics* statistics) + : level(0), currentsector(0), st_gl_mode(mode), + end_sequence(NO_ENDSEQUENCE), levelname(levelname_), flip_level(flip_level_), + best_level_statistics(statistics) { current_ = this; global_frame_counter = 0; game_pause = false; + fps_fps = 0; - fps_timer.init(true); + fps_timer.init(true); frame_timer.init(true); + random_timer.init(true); + frame_rate.set_fps(100); + + context = new DrawingContext(); + + if(flip_levels_mode) + flip_level = true; + + last_swap_point = Vector(-1, -1); + last_swap_stats.reset(); restart_level(); } @@ -81,47 +114,56 @@ GameSession::restart_level() fps_timer.init(true); frame_timer.init(true); + random_timer.init(true); - float old_x_pos = -1; + last_keys.clear(); - if (world) + Vector tux_pos = Vector(-1,-1); + if (currentsector) { // Tux has lost a life, so we try to respawn him at the nearest reset point - old_x_pos = world->get_tux()->base.x; + tux_pos = currentsector->player->base; } - 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); + if(flip_level) + level->do_vertical_flip(); + + global_stats.reset(); + global_stats.set_total_points(COINS_COLLECTED_STAT, level->get_total_coins()); + global_stats.set_total_points(BADGUYS_KILLED_STAT, level->get_total_badguys()); + global_stats.set_total_points(TIME_NEEDED_STAT, level->time_left); + + currentsector = level->get_sector("main"); + if(!currentsector) + Termination::abort("Level has no main sector.", ""); + currentsector->activate("main"); // Set Tux to the nearest reset point - if (old_x_pos != -1) + if(tux_pos.x != -1) { - ResetPoint best_reset_point = { -1, -1 }; - for(std::vector::iterator i = get_level()->reset_points.begin(); - i != get_level()->reset_points.end(); ++i) - { - if (i->x < old_x_pos && best_reset_point.x < i->x) - best_reset_point = *i; - } - - if (best_reset_point.x != -1) - { - world->get_tux()->base.x = best_reset_point.x; - world->get_tux()->base.y = best_reset_point.y; - } + tux_pos = currentsector->get_best_spawn_point(tux_pos); + + if(last_swap_point.x > tux_pos.x) + tux_pos = last_swap_point; + else // new swap point + { + last_swap_point = tux_pos; + + last_swap_stats += global_stats; + } + + currentsector->player->base.x = tux_pos.x; + currentsector->player->base.y = tux_pos.y; + + // has to reset camera on swapping + currentsector->camera->reset(Vector(currentsector->player->base.x, + currentsector->player->base.y)); } - + if (st_gl_mode != ST_GL_DEMO_GAME) { if(st_gl_mode == ST_GL_PLAY || st_gl_mode == ST_GL_LOAD_LEVEL_FILE) @@ -130,37 +172,49 @@ 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(); + SoundManager::get()->halt_music(); char str[60]; - - if (get_level()->img_bkgd) - get_level()->draw_bg(); - else - drawgradient(get_level()->bkgd_top, get_level()->bkgd_bottom); - sprintf(str, "%s", world->get_level()->name.c_str()); - gold_text->drawf(str, 0, 200, A_HMIDDLE, A_TOP, 1); + DrawingContext context; + currentsector->background->draw(context); + +// context.draw_text(gold_text, level->get_name(), Vector(screen->w/2, 160), +// CENTER_ALLIGN, LAYER_FOREGROUND1); + context.draw_center_text(gold_text, level->get_name(), Vector(0, 160), + LAYER_FOREGROUND1); sprintf(str, "TUX x %d", player_status.lives); - white_text->drawf(str, 0, 224, A_HMIDDLE, A_TOP, 1); - - sprintf(str, "by %s", world->get_level()->author.c_str()); - white_small_text->drawf(str, 0, 360, A_HMIDDLE, A_TOP, 1); - + context.draw_text(white_text, str, Vector(screen->w/2, 210), + CENTER_ALLIGN, LAYER_FOREGROUND1); + + if(level->get_author().size()) + context.draw_text(white_small_text, + std::string(_("by ")) + level->get_author(), + Vector(screen->w/2, 350), CENTER_ALLIGN, LAYER_FOREGROUND1); - flipscreen(); + + if(flip_level) + context.draw_text(white_text, + _("Level Vertically Flipped!"), + Vector(screen->w/2, 310), CENTER_ALLIGN, LAYER_FOREGROUND1); + + if(best_level_statistics != NULL) + best_level_statistics->draw_message_info(context, _("Best Level Statistics")); + + context.do_drawing(); SDL_Event event; wait_for_event(event,1000,3000,true); @@ -170,14 +224,17 @@ GameSession::levelintro(void) void GameSession::start_timers() { - time_left.start(world->get_level()->time_left*1000); - st_pause_ticks_init(); - update_time = st_get_ticks(); + time_left.start(level->time_left*1000); + Ticks::pause_init(); + frame_rate.start(); } void GameSession::on_escape_press() { + 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; @@ -187,8 +244,19 @@ GameSession::on_escape_press() } else if (!Menu::current()) { + /* 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 = *(currentsector->player); + tux.key_event((SDLKey)keymap.up, UP); + tux.key_event((SDLKey)keymap.down, UP); + tux.key_event((SDLKey)keymap.left, UP); + tux.key_event((SDLKey)keymap.right, UP); + tux.key_event((SDLKey)keymap.jump, UP); + tux.key_event((SDLKey)keymap.power, UP); + Menu::set_current(game_menu); - st_pause_ticks_start(); + Ticks::pause_start(); } } @@ -197,7 +265,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; @@ -219,13 +287,13 @@ GameSession::process_events() { Menu::current()->event(event); if(!Menu::current()) - st_pause_ticks_stop(); + Ticks::pause_stop(); } switch(event.type) { case SDL_QUIT: /* Quit event - quit: */ - st_abort("Received window close", ""); + Termination::abort("Received window close", ""); break; case SDL_KEYDOWN: /* A keypress! */ @@ -252,7 +320,7 @@ GameSession::process_events() else // normal mode { if(!Menu::current() && !game_pause) - st_pause_ticks_stop(); + Ticks::pause_stop(); SDL_Event event; while (SDL_PollEvent(&event)) @@ -261,27 +329,17 @@ GameSession::process_events() if (Menu::current()) { Menu::current()->event(event); - if(!Menu::current()) - st_pause_ticks_stop(); - - /* 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(); - tux.key_event((SDLKey)keymap.jump, UP); - tux.key_event((SDLKey)keymap.duck, UP); - tux.key_event((SDLKey)keymap.left, UP); - tux.key_event((SDLKey)keymap.right, UP); - tux.key_event((SDLKey)keymap.fire, UP); + if(!Menu::current()) + Ticks::pause_stop(); } else { - Player& tux = *world->get_tux(); + Player& tux = *currentsector->player; switch(event.type) { case SDL_QUIT: /* Quit event - quit: */ - st_abort("Received window close", ""); + Termination::abort("Received window close", ""); break; case SDL_KEYDOWN: /* A keypress! */ @@ -310,66 +368,131 @@ 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()), + LEFT_ALLIGN, LAYER_FOREGROUND1); + context->do_drawing(); + SDL_Delay(1000); + } + break; case SDLK_p: if(!Menu::current()) { + // "lifeup" cheat activates pause cause of the 'p' + // so work around to ignore it + if(compare_last(last_keys, "lifeu")) + break; + if(game_pause) { game_pause = false; - st_pause_ticks_stop(); + Ticks::pause_stop(); } else { game_pause = true; - st_pause_ticks_start(); + Ticks::pause_start(); } } break; - case SDLK_TAB: - if(debug_mode) - { - tux.size = !tux.size; - if(tux.size == BIG) - { - tux.base.height = 64; - } - else - tux.base.height = 32; - } - break; - case SDLK_END: - if(debug_mode) - player_status.distros += 50; - break; - case SDLK_DELETE: - if(debug_mode) - tux.got_power = tux.FIRE_POWER; - break; - case SDLK_HOME: - if(debug_mode) - tux.got_power = tux.ICE_POWER; - break; - case SDLK_INSERT: - if(debug_mode) - tux.invincible_timer.start(TUX_INVINCIBLE_TIME); - break; - case SDLK_l: - if(debug_mode) - --player_status.lives; - break; - case SDLK_s: - if(debug_mode) - player_status.score += 1000; - case SDLK_f: - if(debug_fps) - debug_fps = false; - else - debug_fps = true; - break; default: break; } } + + /* Check if chacrater is ASCII */ + char ch[2]; + if((event.key.keysym.unicode & 0xFF80) == 0) + { + ch[0] = event.key.keysym.unicode & 0x7F; + ch[1] = '\0'; + } + last_keys.append(ch); // add to cheat keys + + // Cheating words (the goal of this is really for debugging, + // but could be used for some cheating, nothing wrong with that) + if(compare_last(last_keys, "grow")) + { + tux.grow(false); + last_keys.clear(); + } + if(compare_last(last_keys, "fire")) + { + tux.grow(false); + tux.got_power = tux.FIRE_POWER; + last_keys.clear(); + } + if(compare_last(last_keys, "ice")) + { + tux.grow(false); + tux.got_power = tux.ICE_POWER; + last_keys.clear(); + } + if(compare_last(last_keys, "lifeup")) + { + player_status.lives++; + last_keys.clear(); + } + if(compare_last(last_keys, "lifedown")) + { + player_status.lives--; + last_keys.clear(); + } + if(compare_last(last_keys, "grease")) + { + tux.physic.set_velocity_x(tux.physic.get_velocity_x()*3); + last_keys.clear(); + } + if(compare_last(last_keys, "invincible")) + { // be invincle for the rest of the level + tux.invincible_timer.start(time_left.get_left()); + last_keys.clear(); + } + if(compare_last(last_keys, "shrink")) + { // remove powerups + tux.kill(tux.SHRINK); + last_keys.clear(); + } + if(compare_last(last_keys, "kill")) + { // kill Tux, but without losing a life + player_status.lives++; + tux.kill(tux.KILL); + last_keys.clear(); + } + if(compare_last(last_keys, "hover")) + { // toggle hover ability on/off + tux.enable_hover = !tux.enable_hover; + last_keys.clear(); + } + if(compare_last(last_keys, "gotoend")) + { // goes to the end of the level + tux.base.x = (currentsector->solids->get_width()*32) - (screen->w*2); + tux.base.y = 0; + currentsector->camera->reset(Vector(tux.base.x, tux.base.y)); + last_keys.clear(); + } + // temporary to help player's choosing a flapping + if(compare_last(last_keys, "marek")) + { + tux.flapping_mode = Player::MAREK_FLAP; + last_keys.clear(); + } + if(compare_last(last_keys, "ricardo")) + { + tux.flapping_mode = Player::RICARDO_FLAP; + last_keys.clear(); + } + if(compare_last(last_keys, "ryan")) + { + tux.flapping_mode = Player::RYAN_FLAP; + last_keys.clear(); + } break; case SDL_JOYAXISMOTION: @@ -394,17 +517,47 @@ GameSession::process_events() else if (event.jaxis.axis == joystick_keymap.y_axis) { if (event.jaxis.value > joystick_keymap.dead_zone) - tux.input.down = DOWN; - else if (event.jaxis.value < -joystick_keymap.dead_zone) + { + tux.input.up = DOWN; tux.input.down = UP; + } + else if (event.jaxis.value < -joystick_keymap.dead_zone) + { + tux.input.up = UP; + tux.input.down = DOWN; + } else - tux.input.down = UP; + { + tux.input.up = DOWN; + tux.input.down = DOWN; + } } break; + + case SDL_JOYHATMOTION: + if(event.jhat.value & SDL_HAT_UP) { + tux.input.up = DOWN; + tux.input.down = UP; + } else if(event.jhat.value & SDL_HAT_DOWN) { + tux.input.up = UP; + tux.input.down = DOWN; + } else if(event.jhat.value & SDL_HAT_LEFT) { + tux.input.left = DOWN; + tux.input.right = UP; + } else if(event.jhat.value & SDL_HAT_RIGHT) { + tux.input.left = UP; + tux.input.right = DOWN; + } else if(event.jhat.value == SDL_HAT_CENTERED) { + tux.input.left = UP; + tux.input.right = UP; + tux.input.up = UP; + tux.input.down = UP; + } + break; case SDL_JOYBUTTONDOWN: if (event.jbutton.button == joystick_keymap.a_button) - tux.input.up = DOWN; + tux.input.jump = DOWN; else if (event.jbutton.button == joystick_keymap.b_button) tux.input.fire = DOWN; else if (event.jbutton.button == joystick_keymap.start_button) @@ -412,7 +565,7 @@ GameSession::process_events() break; case SDL_JOYBUTTONUP: if (event.jbutton.button == joystick_keymap.a_button) - tux.input.up = UP; + tux.input.jump = UP; else if (event.jbutton.button == joystick_keymap.b_button) tux.input.fire = UP; break; @@ -428,24 +581,15 @@ 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; + global_stats += last_swap_stats; // add swap points stats return; } else if(end_sequence == ENDSEQUENCE_RUNNING && endtile && endtile->data >= 1) @@ -455,10 +599,15 @@ GameSession::check_end_conditions() else if(!end_sequence && endtile && endtile->data == 0) { end_sequence = ENDSEQUENCE_RUNNING; - last_x_pos = -1; - music_manager->play_music(level_end_song, 0); endsequence_timer.start(7000); // 5 seconds until we finish the map + last_x_pos = -1; + SoundManager::get()->play_music(level_end_song, 0); tux->invincible_timer.start(7000); //FIXME: Implement a winning timer for the end sequence (with special winning animation etc.) + + // add left time to stats + global_stats.set_points(TIME_NEEDED_STAT, time_left.get_gone() / 1000); + + random_timer.start(200); // start 1st firework } else if (!end_sequence && tux->is_dead()) { @@ -466,9 +615,6 @@ GameSession::check_end_conditions() if (player_status.lives < 0) { // No more lives!? - if(st_gl_mode != ST_GL_TEST) - drawendscreen(); - exit_status = ES_GAME_OVER; } else @@ -483,37 +629,84 @@ 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 = ""; + } + + // on end sequence make a few fireworks + if(end_sequence == ENDSEQUENCE_RUNNING && !random_timer.check() && + currentsector->end_sequence_animation() == FIREWORKS_ENDSEQ_ANIM) + { + Vector epicenter = currentsector->camera->get_translation(); + epicenter.x += screen->w * ((float)rand() / RAND_MAX); + epicenter.y += (screen->h/2) * ((float)rand() / RAND_MAX); + + int red = rand() % 255; // calculate firework color + int green = rand() % red; + currentsector->add_particles(epicenter, 0, 360, Vector(1.4,1.4), + Vector(0,0), 45, Color(red,green,0), 3, 1300, + LAYER_FOREGROUND1+1); + + SoundManager::get()->play_sound(IDToSound(SND_FIREWORKS)); + random_timer.start(rand() % 400 + 600); // next firework } } 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(blue_text, _("PAUSE - Press 'P' To Play"), + Vector(screen->w/2, 230), CENTER_ALLIGN, LAYER_FOREGROUND1+2); + + char str1[60]; + char str2[124]; + sprintf(str1, _("Playing: ")); + sprintf(str2, level->name.c_str()); + + context->draw_text(blue_text, str1, + Vector((screen->w - (blue_text->get_text_width(str1) + white_text->get_text_width(str2)))/2, 340), + LEFT_ALLIGN, LAYER_FOREGROUND1+2); + context->draw_text(white_text, str2, + Vector(((screen->w - (blue_text->get_text_width(str1) + white_text->get_text_width(str2)))/2)+blue_text->get_text_width(str1), 340), + LEFT_ALLIGN, 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 @@ -529,10 +722,10 @@ GameSession::process_menu() switch (game_menu->check()) { case MNID_CONTINUE: - st_pause_ticks_stop(); + Ticks::pause_stop(); break; case MNID_ABORTLEVEL: - st_pause_ticks_stop(); + Ticks::pause_stop(); exit_status = ES_LEVEL_ABORT; break; } @@ -556,7 +749,7 @@ GameSession::run() int fps_cnt = 0; - update_time = last_update_time = st_get_ticks(); + frame_rate.start(); // Eat unneeded events SDL_Event event; @@ -567,7 +760,7 @@ GameSession::run() while (exit_status == ES_NONE) { /* Calculate the movement-factor */ - double frame_ratio = ((double)(update_time-last_update_time))/((double)FRAME_RATE); + double frame_ratio = frame_rate.get(); if(!frame_timer.check()) { @@ -576,7 +769,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(); @@ -607,38 +801,27 @@ GameSession::run() continue; } - /* Set the time of the last update and the time of the current update */ - last_update_time = update_time; - update_time = st_get_ticks(); - - /* Pause till next frame, if the machine running the game is too fast: */ - /* FIXME: Works great for in OpenGl mode, where the CPU doesn't have to do that much. But - the results in SDL mode aren't perfect (thought the 100 FPS are reached), even on an AMD2500+. */ - if(last_update_time >= update_time - 12) - { - SDL_Delay(10); - update_time = st_get_ticks(); - } + frame_rate.update(); /* 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 */ @@ -658,106 +841,105 @@ 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(((int)(x + 1) / 32) * 32, - (int)(y / 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); + SoundManager::get()->play_sound(IDToSound(SND_BRICK), Vector(x, y), Sector::current()->player->get_pos()); } /* (Status): */ void -GameSession::drawstatus() +GameSession::drawstatus(DrawingContext& context) { char str[60]; - - sprintf(str, "%d", player_status.score); - white_text->draw("SCORE", 0, 0, 1); - gold_text->draw(str, 96, 0, 1); + + snprintf(str, 60, " %d", global_stats.get_points(SCORE_STAT)); + context.draw_text(white_text, _("SCORE"), Vector(0, 0), LEFT_ALLIGN, LAYER_FOREGROUND1); + context.draw_text(gold_text, str, Vector(96, 0), LEFT_ALLIGN, 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), + LEFT_ALLIGN, LAYER_FOREGROUND1); } if(!time_left.check()) { - white_text->draw("TIME'S UP", 224, 0, 1); + context.draw_text(white_text, _("TIME's UP"), Vector(screen->w/2, 0), + CENTER_ALLIGN, 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", 224, 0, 1); - gold_text->draw(str, 304, 0, 1); + sprintf(str, " %d", time_left.get_left() / 1000 ); + context.draw_text(white_text, _("TIME"), + Vector(screen->w/2, 0), CENTER_ALLIGN, LAYER_FOREGROUND1); + context.draw_text(gold_text, str, + Vector(screen->w/2 + 4*16, 0), CENTER_ALLIGN, LAYER_FOREGROUND1); } - sprintf(str, "%d", player_status.distros); - white_text->draw("COINS", screen->h, 0, 1); - gold_text->draw(str, 608, 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), + LEFT_ALLIGN, LAYER_FOREGROUND1); + context.draw_text(gold_text, str, + Vector(screen->w - gold_text->get_text_width(" 99"), 0),LEFT_ALLIGN, LAYER_FOREGROUND1); - white_text->draw("LIVES", 480, 20); if (player_status.lives >= 5) { sprintf(str, "%dx", player_status.lives); - gold_text->draw_align(str, 617, 20, A_RIGHT, A_TOP); - tux_life->draw(565+(18*3), 20); + float x = screen->w - gold_text->get_text_width(str) - tux_life->w; + context.draw_text(gold_text, str, Vector(x, 20), LEFT_ALLIGN, 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(565+(18*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), + LEFT_ALLIGN, LAYER_FOREGROUND1); + if(show_fps) { sprintf(str, "%2.1f", fps_fps); - white_text->draw("FPS", screen->h, 40, 1); - gold_text->draw(str, screen->h + 60, 40, 1); + context.draw_text(white_text, "FPS", + Vector(screen->w - white_text->get_text_width("FPS "), 40), + LEFT_ALLIGN, LAYER_FOREGROUND1); + context.draw_text(gold_text, str, + Vector(screen->w-4*16, 40), LEFT_ALLIGN, LAYER_FOREGROUND1); } } void -GameSession::drawendscreen() -{ - char str[80]; - - if (get_level()->img_bkgd) - get_level()->draw_bg(); - else - drawgradient(get_level()->bkgd_top, get_level()->bkgd_bottom); - - blue_text->drawf("GAMEOVER", 0, 200, A_HMIDDLE, A_TOP, 1); - - sprintf(str, "SCORE: %d", player_status.score); - gold_text->drawf(str, 0, 224, A_HMIDDLE, A_TOP, 1); - - sprintf(str, "COINS: %d", player_status.distros); - gold_text->drawf(str, 0, 256, A_HMIDDLE, A_TOP, 1); - - flipscreen(); - - SDL_Event event; - wait_for_event(event,2000,5000,true); -} - -void GameSession::drawresultscreen(void) { char str[80]; - if (get_level()->img_bkgd) - get_level()->draw_bg(); - else - drawgradient(get_level()->bkgd_top, get_level()->bkgd_bottom); + DrawingContext context; + currentsector->background->draw(context); - blue_text->drawf("Result:", 0, 200, A_HMIDDLE, A_TOP, 1); + context.draw_text(blue_text, _("Result:"), Vector(screen->w/2, 200), + CENTER_ALLIGN, LAYER_FOREGROUND1); - sprintf(str, "SCORE: %d", player_status.score); - gold_text->drawf(str, 0, 224, A_HMIDDLE, A_TOP, 1); + sprintf(str, _("SCORE: %d"), global_stats.get_points(SCORE_STAT)); + context.draw_text(gold_text, str, Vector(screen->w/2, 224), CENTER_ALLIGN, 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(gold_text, str, Vector(screen->w/2, 256), CENTER_ALLIGN, LAYER_FOREGROUND1); - flipscreen(); + context.do_drawing(); SDL_Event event; wait_for_event(event,2000,5000,true); @@ -765,30 +947,71 @@ GameSession::drawresultscreen(void) std::string slotinfo(int slot) { - char tmp[1024]; - char slotfile[1024]; + std::string tmp; + std::string slotfile; std::string title; - sprintf(slotfile,"%s/slot%d.stsg",st_save_dir,slot); + std::stringstream stream; + stream << slot; + slotfile = st_save_dir + "/slot" + stream.str() + ".stsg"; - lisp_object_t* savegame = lisp_read_from_file(slotfile); + lisp_object_t* savegame = lisp_read_from_file(slotfile.c_str()); if (savegame) { LispReader reader(lisp_cdr(savegame)); - reader.read_string("title", &title); + reader.read_string("title", title); lisp_free(savegame); } - if (access(slotfile, F_OK) == 0) + if (access(slotfile.c_str(), F_OK) == 0) { if (!title.empty()) - snprintf(tmp,1024,"Slot %d - %s",slot, title.c_str()); + tmp = "Slot " + stream.str() + " - " + title; else - snprintf(tmp, 1024,"Slot %d - Savegame",slot); + tmp = "Slot " + stream.str() + " - Savegame"; } else - sprintf(tmp,"Slot %d - Free",slot); + tmp = std::string(_("Slot")) + " " + stream.str() + " - " + std::string(_("Free")); return tmp; } +bool process_load_game_menu() +{ + int slot = load_game_menu->check(); + + if(slot != -1 && load_game_menu->get_item_by_id(slot).kind == MN_ACTION) + { + std::stringstream stream; + stream << slot; + std::string slotfile = st_save_dir + "/slot" + stream.str() + ".stsg"; + + if (access(slotfile.c_str(), F_OK) != 0) + { + shrink_fade(Vector(screen->w/2,screen->h/2), 600); + draw_intro(); + } + fadeout(256); + DrawingContext context; + context.draw_text(white_text, "Loading...", + Vector(screen->w/2, screen->h/2), CENTER_ALLIGN, LAYER_FOREGROUND1); + context.do_drawing(); + + WorldMapNS::WorldMap worldmap; + + worldmap.set_map_filename("icyisland.stwm"); + // Load the game or at least set the savegame_file variable + worldmap.loadgame(slotfile); + + worldmap.display(); + + Menu::set_current(main_menu); + + Ticks::pause_stop(); + return true; + } + else + { + return false; + } +}