X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=src%2Fgameloop.cpp;h=fb3e557718a47de299cf63951ea99ed0cb1415f6;hb=d26d9e424eed4bd31dfdf023a120e6ebf3270eba;hp=ec7a7c564012dc85e5ef3c07c5d464d79c9e1762;hpb=7ca7b8e7d46020da41a192a7cd82f5cf5a36a9ef;p=supertux.git diff --git a/src/gameloop.cpp b/src/gameloop.cpp index ec7a7c564..fb3e55771 100644 --- a/src/gameloop.cpp +++ b/src/gameloop.cpp @@ -53,13 +53,22 @@ #include "tile.h" #include "particlesystem.h" #include "resources.h" +#include "music_manager.h" GameSession* GameSession::current_ = 0; GameSession::GameSession(const std::string& subset_, int levelnb_, int mode) - : world(0), st_gl_mode(mode), levelnb(levelnb_), subset(subset_) + : world(0), st_gl_mode(mode), levelnb(levelnb_), end_sequence(NO_ENDSEQUENCE), + subset(subset_) { current_ = this; + + global_frame_counter = 0; + game_pause = false; + + fps_timer.init(true); + frame_timer.init(true); + restart_level(); } @@ -68,7 +77,7 @@ GameSession::restart_level() { game_pause = false; exit_status = NONE; - end_sequenze = false; + end_sequence = NO_ENDSEQUENCE; fps_timer.init(true); frame_timer.init(true); @@ -112,7 +121,6 @@ GameSession::restart_level() world->get_tux()->base.y = best_reset_point.y; } } - if (st_gl_mode != ST_GL_DEMO_GAME) { @@ -121,7 +129,8 @@ GameSession::restart_level() } time_left.init(true); - start_timers(); + start_timers(); + world->play_music(LEVEL_MUSIC); } GameSession::~GameSession() @@ -132,9 +141,14 @@ GameSession::~GameSession() void GameSession::levelintro(void) { + music_manager->halt_music(); + char str[60]; - /* Level Intro: */ - clearscreen(0, 0, 0); + + if (get_level()->img_bkgd) + get_level()->img_bkgd->draw(0, 0); + 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); @@ -143,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(); @@ -164,6 +178,9 @@ GameSession::start_timers() void GameSession::on_escape_press() { + if(game_pause) + return; + if(st_gl_mode == ST_GL_TEST) { exit_status = LEVEL_ABORT; @@ -177,42 +194,42 @@ GameSession::on_escape_press() void GameSession::process_events() { - SDL_Event event; - while (SDL_PollEvent(&event)) + if (end_sequence != NO_ENDSEQUENCE) { - /* Check for menu-events, if the menu is shown */ - if (Menu::current()) - { - Menu::current()->event(event); - st_pause_ticks_start(); - } - else if (end_sequenze) - { - Player& tux = *world->get_tux(); - tux.input.left = UP; - tux.input.right = DOWN; - tux.input.up = UP; - tux.input.down = UP; - } + Player& tux = *world->get_tux(); + + tux.input.fire = UP; + tux.input.left = UP; + tux.input.right = DOWN; + tux.input.down = UP; + + if (int(last_x_pos) == int(tux.base.x)) + tux.input.up = DOWN; else + tux.input.up = UP; + + last_x_pos = tux.base.x; + + SDL_Event event; + while (SDL_PollEvent(&event)) { - Player& tux = *world->get_tux(); - - st_pause_ticks_stop(); + /* Check for menu-events, if the menu is shown */ + if (Menu::current()) + { + Menu::current()->event(event); + st_pause_ticks_start(); + } switch(event.type) { case SDL_QUIT: /* Quit event - quit: */ st_abort("Received window close", ""); break; - + case SDL_KEYDOWN: /* A keypress! */ { SDLKey key = event.key.keysym.sym; - - if(tux.key_event(key,DOWN)) - break; - + switch(key) { case SDLK_ESCAPE: /* Escape: Open/Close the menu: */ @@ -222,169 +239,232 @@ GameSession::process_events() break; } } + + case SDL_JOYBUTTONDOWN: + if (event.jbutton.button == joystick_keymap.start_button) + on_escape_press(); break; - case SDL_KEYUP: /* A keyrelease! */ - { - SDLKey key = event.key.keysym.sym; + } + } + } + else // normal mode + { + if(!Menu::current() && !game_pause) + st_pause_ticks_stop(); - if(tux.key_event(key, UP)) + SDL_Event event; + while (SDL_PollEvent(&event)) + { + /* Check for menu-events, if the menu is shown */ + if (Menu::current()) + { + Menu::current()->event(event); + st_pause_ticks_start(); + } + else + { + Player& tux = *world->get_tux(); + + switch(event.type) + { + case SDL_QUIT: /* Quit event - quit: */ + st_abort("Received window close", ""); break; - switch(key) + case SDL_KEYDOWN: /* A keypress! */ { - case SDLK_p: - if(!Menu::current()) + SDLKey key = event.key.keysym.sym; + + if(tux.key_event(key,DOWN)) + break; + + switch(key) { - if(game_pause) - { - game_pause = false; - st_pause_ticks_stop(); - } - else - { - game_pause = true; - st_pause_ticks_start(); - } + case SDLK_ESCAPE: /* Escape: Open/Close the menu: */ + on_escape_press(); + break; + default: + break; } - break; - case SDLK_TAB: - if(debug_mode) + } + break; + case SDL_KEYUP: /* A keyrelease! */ + { + SDLKey key = event.key.keysym.sym; + + if(tux.key_event(key, UP)) + break; + + switch(key) { - tux.size = !tux.size; - if(tux.size == BIG) + case SDLK_p: + if(!Menu::current()) + { + if(game_pause) + { + game_pause = false; + st_pause_ticks_stop(); + } + else + { + game_pause = true; + st_pause_ticks_start(); + } + } + break; + case SDLK_TAB: + if(debug_mode) { - tux.base.height = 64; + 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_coffee = 1; + 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 - tux.base.height = 32; + debug_fps = true; + break; + default: + break; } - break; - case SDLK_END: - if(debug_mode) - player_status.distros += 50; - break; - case SDLK_DELETE: - if(debug_mode) - tux.got_coffee = 1; - 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; } - } - break; + break; - case SDL_JOYAXISMOTION: - if (event.jaxis.axis == joystick_keymap.x_axis) - { - if (event.jaxis.value < -joystick_keymap.dead_zone) - { - tux.input.left = DOWN; - tux.input.right = UP; - } - else if (event.jaxis.value > joystick_keymap.dead_zone) + case SDL_JOYAXISMOTION: + if (event.jaxis.axis == joystick_keymap.x_axis) { - tux.input.left = UP; - tux.input.right = DOWN; + if (event.jaxis.value < -joystick_keymap.dead_zone) + { + tux.input.left = DOWN; + tux.input.right = UP; + } + else if (event.jaxis.value > joystick_keymap.dead_zone) + { + tux.input.left = UP; + tux.input.right = DOWN; + } + else + { + tux.input.left = DOWN; + tux.input.right = DOWN; + } } - else + else if (event.jaxis.axis == joystick_keymap.y_axis) { - tux.input.left = DOWN; - tux.input.right = DOWN; + if (event.jaxis.value > joystick_keymap.dead_zone) + tux.input.down = DOWN; + else if (event.jaxis.value < -joystick_keymap.dead_zone) + tux.input.down = UP; + else + tux.input.down = UP; } - } - 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.down = UP; - else - tux.input.down = UP; - } - break; + break; - case SDL_JOYBUTTONDOWN: - if (event.jbutton.button == joystick_keymap.a_button) - tux.input.up = DOWN; - else if (event.jbutton.button == joystick_keymap.b_button) - tux.input.fire = DOWN; - else if (event.jbutton.button == joystick_keymap.start_button) - on_escape_press(); - break; - case SDL_JOYBUTTONUP: - if (event.jbutton.button == joystick_keymap.a_button) - tux.input.up = UP; - else if (event.jbutton.button == joystick_keymap.b_button) - tux.input.fire = UP; - break; + case SDL_JOYBUTTONDOWN: + if (event.jbutton.button == joystick_keymap.a_button) + tux.input.up = DOWN; + else if (event.jbutton.button == joystick_keymap.b_button) + tux.input.fire = DOWN; + else if (event.jbutton.button == joystick_keymap.start_button) + on_escape_press(); + break; + case SDL_JOYBUTTONUP: + if (event.jbutton.button == joystick_keymap.a_button) + tux.input.up = UP; + else if (event.jbutton.button == joystick_keymap.b_button) + tux.input.fire = UP; + break; - default: - break; - } /* switch */ - } - } /* while */ + default: + break; + } /* switch */ + } + } /* while */ + } } - void GameSession::check_end_conditions() { Player* tux = world->get_tux(); /* End of level? */ - if (tux->base.x >= World::current()->get_level()->endpos + 320) + 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); + } + else if(end_sequence && !endsequence_timer.check()) { exit_status = LEVEL_FINISHED; + return; } - else if (tux->base.x >= World::current()->get_level()->endpos) + else if(end_sequence == ENDSEQUENCE_RUNNING && endtile && endtile->data >= 1) { - end_sequenze = true; - halt_music(); + end_sequence = ENDSEQUENCE_WAITING; } - else + else if(!end_sequence && endtile && endtile->data == 0) { - // 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(); - } + 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 + } + else if (!end_sequence && tux->is_dead()) + { + player_status.bonus = PlayerStatus::NO_BONUS; + 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(); } - } + + return; + } } void GameSession::action(double frame_ratio) { - check_end_conditions(); - if (exit_status == NONE) { // Update Tux and the World @@ -430,10 +510,10 @@ GameSession::process_menu() { switch (game_menu->check()) { - case 2: + case MNID_CONTINUE: st_pause_ticks_stop(); break; - case 5: + case MNID_ABORTLEVEL: st_pause_ticks_stop(); exit_status = LEVEL_ABORT; break; @@ -454,26 +534,11 @@ GameSession::ExitStatus GameSession::run() { Menu::set_current(0); - Player* tux = world->get_tux(); current_ = this; - int fps_cnt; + int fps_cnt = 0; - global_frame_counter = 0; - game_pause = false; - - fps_timer.init(true); - frame_timer.init(true); - - last_update_time = st_get_ticks(); - fps_cnt = 0; - - /* Clear screen: */ - clearscreen(0, 0, 0); - updatescreen(); - - /* Play music: */ - play_current_music(); + update_time = last_update_time = st_get_ticks(); // Eat unneeded events SDL_Event event; @@ -481,7 +546,6 @@ GameSession::run() draw(); - float overlap = 0.0f; while (exit_status == NONE) { /* Calculate the movement-factor */ @@ -494,7 +558,7 @@ GameSession::run() } /* Handle events: */ - tux->input.old_fire = tux->input.fire; + world->get_tux()->input.old_fire = world->get_tux()->input.fire; process_events(); process_menu(); @@ -504,18 +568,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_sequenze) - 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 { @@ -545,19 +603,24 @@ GameSession::run() } /* Handle time: */ - if (time_left.check()) + 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() && !end_sequence) { - /* are we low on time ? */ - if (time_left.get_left() < TIME_WARNING - && (get_current_music() != HURRYUP_MUSIC)) /* play the fast music */ - { - set_current_music(HURRYUP_MUSIC); - play_current_music(); - } + world->play_music(HERRING_MUSIC); + } + /* are we low on time ? */ + else if (time_left.get_left() < TIME_WARNING && !end_sequence) + { + world->play_music(HURRYUP_MUSIC); } - else if(tux->dying == DYING_NOT) + /* or just normal music? */ + else if(world->get_music_type() != LEVEL_MUSIC && !end_sequence) { - tux->kill(KILL); + world->play_music(LEVEL_MUSIC); } /* Calculate frames per second */ @@ -574,12 +637,6 @@ GameSession::run() } } - halt_music(); - - world->get_level()->free_gfx(); - world->get_level()->cleanup(); - world->get_level()->free_song(); - return exit_status; } @@ -607,18 +664,30 @@ 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", 224, 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", 224, 0, 1); + gold_text->draw(str, 304, 0, 1); + } sprintf(str, "%d", player_status.distros); - white_text->draw("DISTROS", screen->h, 0, 1); + white_text->draw("COINS", screen->h, 0, 1); gold_text->draw(str, 608, 0, 1); - white_text->draw("LIVES", screen->h, 20, 1); + 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); + } + else + { + for(int i= 0; i < player_status.lives; ++i) + tux_life->draw(565+(18*i),20); + } if(show_fps) { @@ -626,11 +695,6 @@ GameSession::drawstatus() white_text->draw("FPS", screen->h, 40, 1); gold_text->draw(str, screen->h + 60, 40, 1); } - - for(int i= 0; i < player_status.lives; ++i) - { - tux_life->draw(565+(18*i),20); - } } void @@ -638,7 +702,10 @@ GameSession::drawendscreen() { char str[80]; - clearscreen(0, 0, 0); + 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); @@ -659,14 +726,17 @@ GameSession::drawresultscreen(void) { char str[80]; - clearscreen(0, 0, 0); + 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("Result:", 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, "DISTROS: %d", player_status.distros); + sprintf(str, "COINS: %d", player_status.distros); gold_text->drawf(str, 0, 256, A_HMIDDLE, A_TOP, 1); flipscreen(); @@ -679,10 +749,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);