X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=src%2Fgameloop.cpp;h=625afee490a2d2e13c5765ba7c01f1d2e77d2623;hb=a28d9c1e7fc6b8b2a5c9e139560143e9b74813ea;hp=8e8df1c04b1dd600ae8845d3a88f16b9de019e56;hpb=a8584b00562a912cfeab808bd02aeecc771dd8bb;p=supertux.git diff --git a/src/gameloop.cpp b/src/gameloop.cpp index 8e8df1c04..625afee49 100644 --- a/src/gameloop.cpp +++ b/src/gameloop.cpp @@ -58,7 +58,7 @@ GameSession* GameSession::current_ = 0; GameSession::GameSession(const std::string& subset_, int levelnb_, int mode) - : world(0), st_gl_mode(mode), levelnb(levelnb_), end_sequence(false), + : world(0), st_gl_mode(mode), levelnb(levelnb_), end_sequence(NO_ENDSEQUENCE), subset(subset_) { current_ = this; @@ -76,8 +76,8 @@ void GameSession::restart_level() { game_pause = false; - exit_status = NONE; - end_sequence = false; + exit_status = ES_NONE; + end_sequence = NO_ENDSEQUENCE; fps_timer.init(true); frame_timer.init(true); @@ -146,7 +146,7 @@ GameSession::levelintro(void) char str[60]; if (get_level()->img_bkgd) - get_level()->img_bkgd->draw(0, 0); + get_level()->draw_bg(); else drawgradient(get_level()->bkgd_top, get_level()->bkgd_bottom); @@ -157,7 +157,7 @@ GameSession::levelintro(void) 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, 400, A_HMIDDLE, A_TOP, 1); + white_small_text->drawf(str, 0, 360, A_HMIDDLE, A_TOP, 1); flipscreen(); @@ -178,28 +178,42 @@ GameSession::start_timers() void GameSession::on_escape_press() { + if(world->get_tux()->dying || end_sequence != NO_ENDSEQUENCE) + return; // don't let the player open the menu, when he is dying if(game_pause) return; if(st_gl_mode == ST_GL_TEST) { - exit_status = LEVEL_ABORT; + exit_status = ES_LEVEL_ABORT; } 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 = *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); + Menu::set_current(game_menu); + st_pause_ticks_start(); } } void GameSession::process_events() { - if (end_sequence) + if (end_sequence != NO_ENDSEQUENCE) { Player& tux = *world->get_tux(); - + + tux.input.fire = UP; tux.input.left = UP; - tux.input.right = DOWN; + tux.input.right = DOWN; tux.input.down = UP; if (int(last_x_pos) == int(tux.base.x)) @@ -216,7 +230,8 @@ GameSession::process_events() if (Menu::current()) { Menu::current()->event(event); - st_pause_ticks_start(); + if(!Menu::current()) + st_pause_ticks_stop(); } switch(event.type) @@ -246,7 +261,7 @@ GameSession::process_events() } } } - else + else // normal mode { if(!Menu::current() && !game_pause) st_pause_ticks_stop(); @@ -258,7 +273,8 @@ GameSession::process_events() if (Menu::current()) { Menu::current()->event(event); - st_pause_ticks_start(); + if(!Menu::current()) + st_pause_ticks_stop(); } else { @@ -329,7 +345,11 @@ GameSession::process_events() break; case SDLK_DELETE: if(debug_mode) - tux.got_coffee = 1; + 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) @@ -407,51 +427,62 @@ GameSession::process_events() } } - void GameSession::check_end_conditions() { Player* tux = world->get_tux(); /* End of level? */ - if (tux->base.x >= World::current()->get_level()->endpos + 32 * (get_level()->use_endsequence ? 22 : 10)) + 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) { - exit_status = LEVEL_FINISHED; + 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()) + { + exit_status = ES_LEVEL_FINISHED; + return; } - else if (tux->base.x >= World::current()->get_level()->endpos && !end_sequence) + else if(end_sequence == ENDSEQUENCE_RUNNING && endtile && endtile->data >= 1) { - end_sequence = true; + end_sequence = ENDSEQUENCE_WAITING; + } + else if(!end_sequence && endtile && endtile->data == 0) + { + end_sequence = ENDSEQUENCE_RUNNING; last_x_pos = -1; - music_manager->halt_music(); + music_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.) } - else + else if (!end_sequence && tux->is_dead()) { - // Check End conditions - if (tux->is_dead()) - { - player_status.lives -= 1; - - if (player_status.lives < 0) - { // No more lives!? - if(st_gl_mode != ST_GL_TEST) - drawendscreen(); - - exit_status = GAME_OVER; - } - else - { // Still has lives, so reset Tux to the levelstart - restart_level(); - } + player_status.bonus = PlayerStatus::NO_BONUS; + + if (player_status.lives < 0) + { // No more lives!? + exit_status = ES_GAME_OVER; + } + else + { // Still has lives, so reset Tux to the levelstart + restart_level(); } - } + + return; + } } void GameSession::action(double frame_ratio) { - check_end_conditions(); - - if (exit_status == NONE) + if (exit_status == ES_NONE) { // Update Tux and the World world->action(frame_ratio); @@ -501,7 +532,7 @@ GameSession::process_menu() break; case MNID_ABORTLEVEL: st_pause_ticks_stop(); - exit_status = LEVEL_ABORT; + exit_status = ES_LEVEL_ABORT; break; } } @@ -526,18 +557,13 @@ GameSession::run() update_time = last_update_time = st_get_ticks(); - /* Clear screen: */ - clearscreen(0, 0, 0); - updatescreen(); - // Eat unneeded events SDL_Event event; while (SDL_PollEvent(&event)) {} draw(); - float overlap = 0.0f; - while (exit_status == NONE) + while (exit_status == ES_NONE) { /* Calculate the movement-factor */ double frame_ratio = ((double)(update_time-last_update_time))/((double)FRAME_RATE); @@ -559,18 +585,12 @@ GameSession::run() // determistic and not different on different machines if(!game_pause && !Menu::current()) { - frame_ratio *= game_speed; - frame_ratio += overlap; - while (frame_ratio > 0) - { - // Update the world - if (end_sequence) - action(.5f); - else - action(1.0f); - frame_ratio -= 1.0f; - } - overlap = frame_ratio; + // Update the world + check_end_conditions(); + if (end_sequence == ENDSEQUENCE_RUNNING) + action(frame_ratio/2); + else if(end_sequence == NO_ENDSEQUENCE) + action(frame_ratio); } else { @@ -600,23 +620,22 @@ GameSession::run() } /* Handle time: */ - if (!time_left.check() && world->get_tux()->dying == DYING_NOT) + if (!time_left.check() && world->get_tux()->dying == DYING_NOT + && !end_sequence) world->get_tux()->kill(Player::KILL); /* Handle music: */ - if(world->get_tux()->invincible_timer.check()) + if(world->get_tux()->invincible_timer.check() && !end_sequence) { - if(world->get_music_type() != HERRING_MUSIC) - world->play_music(HERRING_MUSIC); + world->play_music(HERRING_MUSIC); } /* are we low on time ? */ - else if (time_left.get_left() < TIME_WARNING - && (world->get_music_type() == LEVEL_MUSIC)) + else if (time_left.get_left() < TIME_WARNING && !end_sequence) { world->play_music(HURRYUP_MUSIC); } /* or just normal music? */ - else if(world->get_music_type() != LEVEL_MUSIC) + else if(world->get_music_type() != LEVEL_MUSIC && !end_sequence) { world->play_music(LEVEL_MUSIC); } @@ -662,69 +681,46 @@ GameSession::drawstatus() white_text->draw("Press ESC To Return",0,20,1); } - 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); - } + if(!time_left.check()) { + white_text->draw("TIME'S UP", screen->w/2 - white_text->w*8, 0, 1); + } 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", player_status.distros); - white_text->draw("COINS", screen->h, 0, 1); - gold_text->draw(str, 608, 0, 1); + white_text->draw("COINS", screen->w - white_text->w*9, 0, 1); + gold_text->draw(str, screen->w - gold_text->w*2, 0, 1); - white_text->draw("LIVES", 480, 20); + 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(str, 585, 20); - tux_life->draw(565+(18*3), 20); + gold_text->draw_align(str, screen->w - gold_text->w, 20, A_RIGHT, A_TOP); + tux_life->draw(screen->w - gold_text->w, 20); } else { for(int i= 0; i < player_status.lives; ++i) - tux_life->draw(565+(18*i),20); + tux_life->draw(screen->w - tux_life->w*4 +(tux_life->w*i), 20); } 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); + white_text->draw("FPS", screen->w - white_text->w*9, 40, 1); + gold_text->draw_align(str, screen->w, 40, A_RIGHT, A_TOP); } } void -GameSession::drawendscreen() -{ - char str[80]; - - if (get_level()->img_bkgd) - get_level()->img_bkgd->draw(0, 0); - 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()->img_bkgd->draw(0, 0); + get_level()->draw_bg(); else drawgradient(get_level()->bkgd_top, get_level()->bkgd_bottom); @@ -746,10 +742,24 @@ std::string slotinfo(int slot) { char tmp[1024]; char slotfile[1024]; + std::string title; sprintf(slotfile,"%s/slot%d.stsg",st_save_dir,slot); + lisp_object_t* savegame = lisp_read_from_file(slotfile); + if (savegame) + { + LispReader reader(lisp_cdr(savegame)); + reader.read_string("title", &title); + lisp_free(savegame); + } + if (access(slotfile, F_OK) == 0) - sprintf(tmp,"Slot %d - Savegame",slot); + { + if (!title.empty()) + snprintf(tmp,1024,"Slot %d - %s",slot, title.c_str()); + else + snprintf(tmp, 1024,"Slot %d - Savegame",slot); + } else sprintf(tmp,"Slot %d - Free",slot);