X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=src%2Fgameloop.cpp;h=e7f1c92b3857ae65c3d0cbe49ca29a65ec73bddb;hb=f54737bb28bec638b9f436d023b9f21fec2caadd;hp=3a33cdbbcf217609c33705eff02a55cd4533720b;hpb=9599042661b468aae7bd34dca05441c0ebc93ad7;p=supertux.git diff --git a/src/gameloop.cpp b/src/gameloop.cpp index 3a33cdbbc..e7f1c92b3 100644 --- a/src/gameloop.cpp +++ b/src/gameloop.cpp @@ -62,6 +62,7 @@ #include "statistics.h" #include "timer.h" #include "object/fireworks.h" +#include "textscroller.h" GameSession* GameSession::current_ = 0; @@ -91,9 +92,6 @@ GameSession::GameSession(const std::string& levelfile_, int mode, context = new DrawingContext(); - last_swap_point = Vector(-1, -1); - last_swap_stats.reset(); - restart_level(); } @@ -106,15 +104,6 @@ GameSession::restart_level() last_keys.clear(); -#if 0 - Vector tux_pos = Vector(-1,-1); - if (currentsector) - { - // Tux has lost a life, so we try to respawn him at the nearest reset point - tux_pos = currentsector->player->base; - } -#endif - delete level; currentsector = 0; @@ -126,40 +115,23 @@ GameSession::restart_level() global_stats.set_total_points(BADGUYS_KILLED_STAT, level->get_total_badguys()); global_stats.set_total_points(TIME_NEEDED_STAT, level->timelimit); - currentsector = level->get_sector("main"); - if(!currentsector) - Termination::abort("Level has no main sector.", ""); - currentsector->activate("main"); - -#if 0 - // Set Tux to the nearest reset point - 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)); - } -#endif - - if (st_gl_mode != ST_GL_DEMO_GAME) - { - if(st_gl_mode == ST_GL_PLAY || st_gl_mode == ST_GL_LOAD_LEVEL_FILE) - levelintro(); + if(reset_sector != "") { + currentsector = level->get_sector(reset_sector); + if(!currentsector) { + std::stringstream msg; + msg << "Couldn't find sector '" << reset_sector << "' for resetting tux."; + throw std::runtime_error(msg.str()); } + currentsector->activate(reset_pos); + } else { + currentsector = level->get_sector("main"); + if(!currentsector) + throw std::runtime_error("Couldn't find main sector"); + currentsector->activate("main"); + } + + if(st_gl_mode == ST_GL_PLAY || st_gl_mode == ST_GL_LOAD_LEVEL_FILE) + levelintro(); start_timers(); currentsector->play_music(LEVEL_MUSIC); @@ -172,7 +144,7 @@ GameSession::~GameSession() } void -GameSession::levelintro(void) +GameSession::levelintro() { SoundManager::get()->halt_music(); @@ -187,20 +159,20 @@ GameSession::levelintro(void) } } -// context.draw_text(gold_text, level->get_name(), Vector(screen->w/2, 160), +// context.draw_text(gold_text, level->get_name(), Vector(SCREEN_WIDTH/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(white_text, str, Vector(screen->w/2, 210), + context.draw_text(white_text, str, Vector(SCREEN_WIDTH/2, 210), CENTER_ALLIGN, LAYER_FOREGROUND1); if((level->get_author().size()) && (level->get_author() != "SuperTux Team")) //TODO make author check case/blank-insensitive context.draw_text(white_small_text, std::string(_("contributed by ")) + level->get_author(), - Vector(screen->w/2, 350), CENTER_ALLIGN, LAYER_FOREGROUND1); + Vector(SCREEN_WIDTH/2, 350), CENTER_ALLIGN, LAYER_FOREGROUND1); if(best_level_statistics != NULL) @@ -352,7 +324,7 @@ GameSession::process_events() snprintf(buf, sizeof(buf), "P: %4.1f,%4.1f", tux.get_pos().x, tux.get_pos().y); context->draw_text(white_text, buf, - Vector(0, screen->h - white_text->get_height()), + Vector(0, SCREEN_HEIGHT - white_text->get_height()), LEFT_ALLIGN, LAYER_FOREGROUND1); context->do_drawing(); SDL_Delay(1000); @@ -383,13 +355,13 @@ GameSession::process_events() } } - /* 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'; - } + /* 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 handle_cheats(); break; @@ -486,17 +458,15 @@ GameSession::handle_cheats() // 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); + tux.set_bonus(GROWUP_BONUS, false); last_keys.clear(); } if(compare_last(last_keys, "fire")) { - tux.grow(false); - tux.got_power = tux.FIRE_POWER; + tux.set_bonus(FIRE_BONUS, false); last_keys.clear(); } if(compare_last(last_keys, "ice")) { - tux.grow(false); - tux.got_power = tux.ICE_POWER; + tux.set_bonus(ICE_BONUS, false); last_keys.clear(); } if(compare_last(last_keys, "lifeup")) { @@ -540,7 +510,7 @@ GameSession::handle_cheats() if(compare_last(last_keys, "gotoend")) { // goes to the end of the level tux.move(Vector( - (currentsector->solids->get_width()*32) - (screen->w*2), 0)); + (currentsector->solids->get_width()*32) - (SCREEN_WIDTH*2), 0)); currentsector->camera->reset( Vector(tux.get_pos().x, tux.get_pos().y)); last_keys.clear(); @@ -572,12 +542,9 @@ GameSession::check_end_conditions() /* End of level? */ if(end_sequence && endsequence_timer.check()) { - exit_status = ES_LEVEL_FINISHED; - global_stats += last_swap_stats; // add swap points stats - return; + exit_status = ES_LEVEL_FINISHED; + return; } else if (!end_sequence && tux->is_dead()) { - 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 @@ -592,19 +559,22 @@ void GameSession::action(float elapsed_time) { // advance timers - if (exit_status == ES_NONE && !currentsector->player->growing_timer.check()) - { - // Update Tux and the World - currentsector->action(elapsed_time); - } + if(!currentsector->player->growing_timer.started()) { + // Update Tux and the World + currentsector->action(elapsed_time); + } // respawning in new sector? if(newsector != "" && newspawnpoint != "") { Sector* sector = level->get_sector(newsector); + if(sector == 0) { + std::cerr << "Sector '" << newsector << "' not found.\n"; + } + sector->activate(newspawnpoint); + sector->play_music(LEVEL_MUSIC); currentsector = sector; - currentsector->activate(newspawnpoint); - currentsector->play_music(LEVEL_MUSIC); - newsector = newspawnpoint = ""; + newsector = ""; + newspawnpoint = ""; } } @@ -615,46 +585,46 @@ GameSession::draw() drawstatus(*context); if(game_pause) - { - int x = screen->h / 20; - for(int i = 0; i < x; ++i) - { - 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); - } - 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); - } + draw_pause(); - if(Menu::current()) - { - Menu::current()->draw(*context); - mouse_cursor->draw(*context); - } + if(Menu::current()) { + Menu::current()->draw(*context); + mouse_cursor->draw(*context); + } context->do_drawing(); } void +GameSession::draw_pause() +{ + int x = SCREEN_HEIGHT / 20; + for(int i = 0; i < x; ++i) { + context->draw_filled_rect( + Vector(i % 2 ? (pause_menu_frame * i)%SCREEN_WIDTH : + -((pause_menu_frame * i)%SCREEN_WIDTH) + ,(i*20+pause_menu_frame)%SCREEN_HEIGHT), + Vector(SCREEN_WIDTH,10), + Color(20,20,20, rand() % 20 + 1), LAYER_FOREGROUND1+1); + } + context->draw_filled_rect( + Vector(0,0), Vector(SCREEN_WIDTH, SCREEN_HEIGHT), + Color(rand() % 50, rand() % 50, rand() % 50, 128), LAYER_FOREGROUND1); + context->draw_text(blue_text, _("PAUSE - Press 'P' To Play"), + Vector(SCREEN_WIDTH/2, 230), CENTER_ALLIGN, LAYER_FOREGROUND1+2); + + const char* str1 = _("Playing: "); + const char* str2 = level->get_name().c_str(); + + context->draw_text(blue_text, str1, + Vector((SCREEN_WIDTH - (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_WIDTH - (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); +} + +void GameSession::process_menu() { Menu* menu = Menu::current(); @@ -686,6 +656,7 @@ GameSession::process_menu() } } + GameSession::ExitStatus GameSession::run() { @@ -693,6 +664,7 @@ GameSession::run() current_ = this; int fps_cnt = 0; + double fps_nextframe_ticks; // fps regulating code // Eat unneeded events SDL_Event event; @@ -703,6 +675,7 @@ GameSession::run() Uint32 lastticks = SDL_GetTicks(); fps_ticks = SDL_GetTicks(); + fps_nextframe_ticks = SDL_GetTicks(); // fps regulating code while (exit_status == ES_NONE) { Uint32 ticks = SDL_GetTicks(); @@ -712,8 +685,27 @@ GameSession::run() lastticks = ticks; // 40fps is minimum - if(elapsed_time > .025) - elapsed_time = .025; + if(elapsed_time > 0.025){ + elapsed_time = 0.025; + } + + // fps regualting code + const double wantedFps= 60.0; // set to 60 by now + while (fps_nextframe_ticks > SDL_GetTicks()){ + /* just wait */ + // If we really have to wait long, then do an imprecise SDL_Delay() + if (fps_nextframe_ticks - SDL_GetTicks() > 15){ + SDL_Delay(5); + } + + } + float diff = SDL_GetTicks() - fps_nextframe_ticks; + if (diff > 5.0) + fps_nextframe_ticks = SDL_GetTicks() + (1000.0 / wantedFps); // sets the ticks that must have elapsed + else + fps_nextframe_ticks += 1000.0 / wantedFps; // sets the ticks that must have elapsed + // in order for the next frame to start. + /* Handle events: */ currentsector->player->input.old_fire = currentsector->player->input.fire; @@ -795,6 +787,36 @@ GameSession::respawn(const std::string& sector, const std::string& spawnpoint) } void +GameSession::set_reset_point(const std::string& sector, const Vector& pos) +{ + reset_sector = sector; + reset_pos = pos; +} + +void +GameSession::display_info_box(const std::string& text) +{ + InfoBox* box = new InfoBox(text); + + bool running = true; + while(running) { + SDL_Event event; + while (SDL_PollEvent(&event)) { + switch(event.type) { + case SDL_KEYDOWN: + running = false; + break; + } + } + + box->draw(*context); + draw(); + } + + delete box; +} + +void GameSession::start_sequence(const std::string& sequencename) { if(sequencename == "endsequence" || sequencename == "fireworks") { @@ -814,6 +836,8 @@ GameSession::start_sequence(const std::string& sequencename) if(sequencename == "fireworks") { currentsector->add_object(new Fireworks()); } + } else if(sequencename == "stoptux") { + end_sequence = ENDSEQUENCE_WAITING; } else { std::cout << "Unknown sequence '" << sequencename << "'.\n"; } @@ -836,52 +860,52 @@ GameSession::drawstatus(DrawingContext& context) } if(time_left.get_timeleft() < 0) { - context.draw_text(white_text, _("TIME's UP"), Vector(screen->w/2, 0), + context.draw_text(white_text, _("TIME's UP"), Vector(SCREEN_WIDTH/2, 0), CENTER_ALLIGN, LAYER_FOREGROUND1); } else if (time_left.get_timeleft() > TIME_WARNING || int(global_time * 2.5) % 2) { sprintf(str, " %d", int(time_left.get_timeleft())); context.draw_text(white_text, _("TIME"), - Vector(screen->w/2, 0), CENTER_ALLIGN, LAYER_FOREGROUND1); + Vector(SCREEN_WIDTH/2, 0), CENTER_ALLIGN, LAYER_FOREGROUND1); context.draw_text(gold_text, str, - Vector(screen->w/2 + 4*16, 0), CENTER_ALLIGN, LAYER_FOREGROUND1); + Vector(SCREEN_WIDTH/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), + Vector(SCREEN_WIDTH - 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); + Vector(SCREEN_WIDTH - 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; + float x = SCREEN_WIDTH - 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), + context.draw_surface(tux_life, Vector(SCREEN_WIDTH - 16, 20), LAYER_FOREGROUND1); } else { for(int i= 0; i < player_status.lives; ++i) context.draw_surface(tux_life, - Vector(screen->w - tux_life->w*4 +(tux_life->w*i), 20), + Vector(SCREEN_WIDTH - 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), + Vector(SCREEN_WIDTH - 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); context.draw_text(white_text, "FPS", - Vector(screen->w - white_text->get_text_width("FPS "), 40), + Vector(SCREEN_WIDTH - 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); + Vector(SCREEN_WIDTH-4*16, 40), LEFT_ALLIGN, LAYER_FOREGROUND1); } } @@ -899,14 +923,14 @@ GameSession::drawresultscreen() } } - context.draw_text(blue_text, _("Result:"), Vector(screen->w/2, 200), + context.draw_text(blue_text, _("Result:"), Vector(SCREEN_WIDTH/2, 200), CENTER_ALLIGN, LAYER_FOREGROUND1); 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); + context.draw_text(gold_text, str, Vector(SCREEN_WIDTH/2, 224), CENTER_ALLIGN, LAYER_FOREGROUND1); sprintf(str, _("COINS: %d"), player_status.distros); - context.draw_text(gold_text, str, Vector(screen->w/2, 256), CENTER_ALLIGN, LAYER_FOREGROUND1); + context.draw_text(gold_text, str, Vector(SCREEN_WIDTH/2, 256), CENTER_ALLIGN, LAYER_FOREGROUND1); context.do_drawing(); @@ -953,7 +977,7 @@ bool process_load_game_menu() fadeout(256); DrawingContext context; context.draw_text(white_text, "Loading...", - Vector(screen->w/2, screen->h/2), CENTER_ALLIGN, LAYER_FOREGROUND1); + Vector(SCREEN_WIDTH/2, SCREEN_HEIGHT/2), CENTER_ALLIGN, LAYER_FOREGROUND1); context.do_drawing(); WorldMapNS::WorldMap worldmap;