X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=src%2Fgameloop.cpp;h=d05379f9dd3d760b87592cf88059d714dbe46798;hb=546364c9567ef212ea9276201facf73f5ada696a;hp=a8ab4fce7aa38d267d5b96aa04a1ec0b6da11767;hpb=a2857397f9afd626046a2005d2614a14d9e11804;p=supertux.git diff --git a/src/gameloop.cpp b/src/gameloop.cpp index a8ab4fce7..d05379f9d 100644 --- a/src/gameloop.cpp +++ b/src/gameloop.cpp @@ -78,9 +78,10 @@ if(haystack.compare(haystack_size-needle_size, needle_size, needle) == 0) return false; } -GameSession::GameSession(const std::string& levelname_, int mode, bool flip_level_) +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_) + end_sequence(NO_ENDSEQUENCE), levelname(levelname_), flip_level(flip_level_), + best_level_statistics(statistics) { current_ = this; @@ -98,6 +99,9 @@ GameSession::GameSession(const std::string& levelname_, int mode, bool flip_leve if(flip_levels_mode) flip_level = true; + last_swap_point = Vector(-1, -1); + last_swap_stats.reset(); + restart_level(); } @@ -128,6 +132,11 @@ GameSession::restart_level() 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.", ""); @@ -137,9 +146,19 @@ GameSession::restart_level() if(tux_pos.x != -1) { 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)); @@ -151,8 +170,6 @@ GameSession::restart_level() levelintro(); } - global_stats.reset(); - time_left.init(true); start_timers(); currentsector->play_music(LEVEL_MUSIC); @@ -174,23 +191,28 @@ GameSession::levelintro(void) DrawingContext context; currentsector->background->draw(context); - context.draw_text_center(gold_text, level->get_name(), Vector(0, 220), +// 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); - context.draw_text_center(white_text, str, Vector(0, 240), - LAYER_FOREGROUND1); + context.draw_text(white_text, str, Vector(screen->w/2, 210), + CENTER_ALLIGN, LAYER_FOREGROUND1); if(level->get_author().size()) - context.draw_text_center(white_small_text, + context.draw_text(white_small_text, std::string(_("by ")) + level->get_author(), - Vector(0, 400), LAYER_FOREGROUND1); + Vector(screen->w/2, 350), CENTER_ALLIGN, LAYER_FOREGROUND1); if(flip_level) - context.draw_text_center(white_text, + context.draw_text(white_text, _("Level Vertically Flipped!"), - Vector(0, 310), LAYER_FOREGROUND1); + 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(); @@ -226,11 +248,12 @@ GameSession::on_escape_press() 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.jump, UP); - tux.key_event((SDLKey)keymap.duck, UP); + 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.fire, UP); + tux.key_event((SDLKey)keymap.jump, UP); + tux.key_event((SDLKey)keymap.power, UP); Menu::set_current(game_menu); Ticks::pause_start(); @@ -353,7 +376,7 @@ GameSession::process_events() tux.base.x, tux.base.y); context->draw_text(white_text, buf, Vector(0, screen->h - white_text->get_height()), - LAYER_FOREGROUND1); + LEFT_ALLIGN, LAYER_FOREGROUND1); context->do_drawing(); SDL_Delay(1000); } @@ -361,6 +384,11 @@ GameSession::process_events() 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; @@ -410,30 +438,61 @@ GameSession::process_events() { player_status.lives++; last_keys.clear(); - // "lifeup" activates pause cause of the 'p' - // so work around to ignore it - if(game_pause) - { - game_pause = false; - Ticks::pause_stop(); - } - else - { - game_pause = true; - Ticks::pause_start(); - } } 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: @@ -458,11 +517,20 @@ 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; @@ -489,7 +557,7 @@ GameSession::process_events() 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) @@ -497,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; @@ -521,6 +589,7 @@ GameSession::check_end_conditions() 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) @@ -530,11 +599,15 @@ GameSession::check_end_conditions() else if(!end_sequence && endtile && endtile->data == 0) { end_sequence = ENDSEQUENCE_RUNNING; - random_timer.start(200); // start 1st firework + endsequence_timer.start(7000); // 5 seconds until we finish the map last_x_pos = -1; SoundManager::get()->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.) + + // 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()) { @@ -572,7 +645,8 @@ GameSession::action(double frame_ratio) } // on end sequence make a few fireworks - if(end_sequence == ENDSEQUENCE_RUNNING && !random_timer.check()) + 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); @@ -580,8 +654,9 @@ GameSession::action(double frame_ratio) int red = rand() % 255; // calculate firework color int green = rand() % red; - currentsector->add_particles(epicenter, Vector(1.4,1.4), Vector(0,0), - 45, Color(red,green,0), 3, 1300); + 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 @@ -609,8 +684,8 @@ GameSession::draw() 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); + 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]; @@ -619,10 +694,10 @@ GameSession::draw() context->draw_text(blue_text, str1, Vector((screen->w - (blue_text->get_text_width(str1) + white_text->get_text_width(str2)))/2, 340), - LAYER_FOREGROUND1+2); + 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), - LAYER_FOREGROUND1+2); + LEFT_ALLIGN, LAYER_FOREGROUND1+2); } if(Menu::current()) @@ -789,38 +864,38 @@ GameSession::drawstatus(DrawingContext& context) char str[60]; snprintf(str, 60, " %d", global_stats.get_points(SCORE_STAT)); - context.draw_text(white_text, _("SCORE"), Vector(0, 0), LAYER_FOREGROUND1); - context.draw_text(gold_text, str, Vector(96, 0), LAYER_FOREGROUND1); + 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) { context.draw_text(white_text, _("Press ESC To Return"), Vector(0,20), - LAYER_FOREGROUND1); + LEFT_ALLIGN, LAYER_FOREGROUND1); } if(!time_left.check()) { - context.draw_text_center(white_text, _("TIME's UP"), Vector(0, 0), - LAYER_FOREGROUND1); + 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 ); - 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); + 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); context.draw_text(white_text, _("COINS"), Vector(screen->w - white_text->get_text_width(_("COINS"))-white_text->get_text_width(" 99"), 0), - LAYER_FOREGROUND1); + LEFT_ALLIGN, LAYER_FOREGROUND1); context.draw_text(gold_text, str, - Vector(screen->w - gold_text->get_text_width(" 99"), 0),LAYER_FOREGROUND1); + Vector(screen->w - gold_text->get_text_width(" 99"), 0),LEFT_ALLIGN, LAYER_FOREGROUND1); if (player_status.lives >= 5) { sprintf(str, "%dx", player_status.lives); 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_text(gold_text, str, Vector(x, 20), LEFT_ALLIGN, LAYER_FOREGROUND1); context.draw_surface(tux_life, Vector(screen->w - 16, 20), LAYER_FOREGROUND1); } @@ -834,16 +909,16 @@ GameSession::drawstatus(DrawingContext& context) context.draw_text(white_text, _("LIVES"), Vector(screen->w - white_text->get_text_width(_("LIVES")) - white_text->get_text_width(" 99"), 20), - LAYER_FOREGROUND1); + LEFT_ALLIGN, LAYER_FOREGROUND1); if(show_fps) { sprintf(str, "%2.1f", fps_fps); context.draw_text(white_text, "FPS", Vector(screen->w - white_text->get_text_width("FPS "), 40), - LAYER_FOREGROUND1); + LEFT_ALLIGN, LAYER_FOREGROUND1); context.draw_text(gold_text, str, - Vector(screen->w-4*16, 40), LAYER_FOREGROUND1); + Vector(screen->w-4*16, 40), LEFT_ALLIGN, LAYER_FOREGROUND1); } } @@ -855,14 +930,14 @@ GameSession::drawresultscreen(void) DrawingContext context; currentsector->background->draw(context); - context.draw_text_center(blue_text, _("Result:"), Vector(0, 200), - LAYER_FOREGROUND1); + context.draw_text(blue_text, _("Result:"), Vector(screen->w/2, 200), + CENTER_ALLIGN, LAYER_FOREGROUND1); sprintf(str, _("SCORE: %d"), global_stats.get_points(SCORE_STAT)); - context.draw_text_center(gold_text, str, Vector(0, 224), LAYER_FOREGROUND1); + context.draw_text(gold_text, str, Vector(screen->w/2, 224), CENTER_ALLIGN, LAYER_FOREGROUND1); sprintf(str, _("COINS: %d"), player_status.distros); - context.draw_text_center(gold_text, str, Vector(0, 256), LAYER_FOREGROUND1); + context.draw_text(gold_text, str, Vector(screen->w/2, 256), CENTER_ALLIGN, LAYER_FOREGROUND1); context.do_drawing(); @@ -912,19 +987,19 @@ bool process_load_game_menu() if (access(slotfile.c_str(), F_OK) != 0) { + shrink_fade(Vector(screen->w/2,screen->h/2), 600); draw_intro(); } - // shrink_fade(Point((screen->w/2),(screen->h/2)), 1000); fadeout(256); - DrawingContext context; - context.draw_text_center(white_text, "Loading...", - Vector(0, screen->h/2), LAYER_FOREGROUND1); + 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);