X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=src%2Fgameloop.cpp;h=3b593f955e95d12961ecde83c8e8385aea9850e7;hb=626ab69641b179048b9d0fc528cd1626886fe9db;hp=2947f848ca284bcf6e002fe95279f6a1dc1ed453;hpb=6e843b1780f62f45b7021bd8c38181aa211588ee;p=supertux.git diff --git a/src/gameloop.cpp b/src/gameloop.cpp index 2947f848c..3b593f955 100644 --- a/src/gameloop.cpp +++ b/src/gameloop.cpp @@ -18,7 +18,6 @@ // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - #include #include @@ -31,35 +30,35 @@ #include #include #include +#include -#include "SDL.h" +#include #ifndef WIN32 #include #include #endif -#include "defines.h" #include "app/globals.h" #include "gameloop.h" #include "video/screen.h" #include "app/setup.h" -#include "high_scores.h" #include "gui/menu.h" #include "sector.h" -#include "player.h" #include "level.h" -#include "scene.h" #include "tile.h" -#include "particlesystem.h" +#include "player_status.h" +#include "object/particlesystem.h" +#include "object/background.h" +#include "object/tilemap.h" +#include "object/camera.h" +#include "object/player.h" +#include "lisp/lisp.h" +#include "lisp/parser.h" #include "resources.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" #include "timer.h" #include "object/fireworks.h" @@ -80,10 +79,10 @@ bool compare_last(std::string& haystack, std::string needle) } GameSession::GameSession(const std::string& levelfile_, int mode, - bool flip_level_, Statistics* statistics) + Statistics* statistics) : level(0), currentsector(0), st_gl_mode(mode), end_sequence(NO_ENDSEQUENCE), levelfile(levelfile_), - flip_level(flip_level_), best_level_statistics(statistics) + best_level_statistics(statistics) { current_ = this; @@ -92,12 +91,6 @@ GameSession::GameSession(const std::string& levelfile_, int mode, context = new DrawingContext(); - if(flip_levels_mode) - flip_level = true; - - last_swap_point = Vector(-1, -1); - last_swap_stats.reset(); - restart_level(); } @@ -124,48 +117,29 @@ GameSession::restart_level() level = new Level; level->load(levelfile); - 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->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); @@ -178,15 +152,20 @@ GameSession::~GameSession() } void -GameSession::levelintro(void) +GameSession::levelintro() { SoundManager::get()->halt_music(); char str[60]; DrawingContext context; - if(currentsector->background) - currentsector->background->draw(context); + for(Sector::GameObjects::iterator i = currentsector->gameobjects.begin(); + i != currentsector->gameobjects.end(); ++i) { + Background* background = dynamic_cast (*i); + if(background) { + background->draw(context); + } + } // context.draw_text(gold_text, level->get_name(), Vector(screen->w/2, 160), // CENTER_ALLIGN, LAYER_FOREGROUND1); @@ -204,11 +183,6 @@ GameSession::levelintro(void) Vector(screen->w/2, 350), CENTER_ALLIGN, LAYER_FOREGROUND1); - 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")); @@ -229,32 +203,18 @@ GameSession::start_timers() void GameSession::on_escape_press() { - if(currentsector->player->dying || end_sequence != NO_ENDSEQUENCE) + if(currentsector->player->is_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 = 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 = *(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); - Ticks::pause_start(); - } + if(st_gl_mode == ST_GL_TEST) { + exit_status = ES_LEVEL_ABORT; + } else if (!Menu::current()) { + Menu::set_current(game_menu); + Ticks::pause_start(); + } } void @@ -264,15 +224,15 @@ GameSession::process_events() { Player& tux = *currentsector->player; - tux.input.fire = UP; - tux.input.left = UP; - tux.input.right = DOWN; - tux.input.down = UP; + tux.input.fire = false; + tux.input.left = false; + tux.input.right = true; + tux.input.down = false; if (int(last_x_pos) == int(tux.get_pos().x)) - tux.input.up = DOWN; + tux.input.up = true; else - tux.input.up = UP; + tux.input.up = false; last_x_pos = tux.get_pos().x; @@ -343,7 +303,7 @@ GameSession::process_events() { SDLKey key = event.key.keysym.sym; - if(tux.key_event(key,DOWN)) + if(tux.key_event(key, true)) break; switch(key) @@ -360,7 +320,7 @@ GameSession::process_events() { SDLKey key = event.key.keysym.sym; - if(tux.key_event(key, UP)) + if(tux.key_event(key, false)) break; switch(key) @@ -403,101 +363,15 @@ 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 - - // 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(10000); - 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, "grid")) - { // toggle debug grid - debug_grid = !debug_grid; - 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.move(Vector( - (currentsector->solids->get_width()*32) - - (screen->w*2), - 0)); - currentsector->camera->reset( - Vector(tux.get_pos().x, tux.get_pos().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(); - } + handle_cheats(); break; case SDL_JOYAXISMOTION: @@ -505,74 +379,75 @@ GameSession::process_events() { if (event.jaxis.value < -joystick_keymap.dead_zone) { - tux.input.left = DOWN; - tux.input.right = UP; + tux.input.left = true; + tux.input.right = false; } else if (event.jaxis.value > joystick_keymap.dead_zone) { - tux.input.left = UP; - tux.input.right = DOWN; + tux.input.left = false; + tux.input.right = true; } else { - tux.input.left = DOWN; - tux.input.right = DOWN; + tux.input.left = false; + tux.input.right = false; } } else if (event.jaxis.axis == joystick_keymap.y_axis) { if (event.jaxis.value > joystick_keymap.dead_zone) { - tux.input.up = DOWN; - tux.input.down = UP; + tux.input.up = true; + tux.input.down = false; } else if (event.jaxis.value < -joystick_keymap.dead_zone) { - tux.input.up = UP; - tux.input.down = DOWN; + tux.input.up = false; + tux.input.down = true; } else { - tux.input.up = DOWN; - tux.input.down = DOWN; + tux.input.up = false; + tux.input.down = false; } } break; case SDL_JOYHATMOTION: if(event.jhat.value & SDL_HAT_UP) { - tux.input.up = DOWN; - tux.input.down = UP; + tux.input.up = true; + tux.input.down = false; } else if(event.jhat.value & SDL_HAT_DOWN) { - tux.input.up = UP; - tux.input.down = DOWN; + tux.input.up = false; + tux.input.down = true; } else if(event.jhat.value & SDL_HAT_LEFT) { - tux.input.left = DOWN; - tux.input.right = UP; + tux.input.left = true; + tux.input.right = false; } else if(event.jhat.value & SDL_HAT_RIGHT) { - tux.input.left = UP; - tux.input.right = DOWN; + tux.input.left = false; + tux.input.right = true; } else if(event.jhat.value == SDL_HAT_CENTERED) { - tux.input.left = UP; - tux.input.right = UP; - tux.input.up = UP; - tux.input.down = UP; + tux.input.left = false; + tux.input.right = false; + tux.input.up = false; + tux.input.down = false; } break; case SDL_JOYBUTTONDOWN: + // FIXME: I assume we have to set old_jump and stuff here?!? if (event.jbutton.button == joystick_keymap.a_button) - tux.input.jump = DOWN; + tux.input.jump = true; else if (event.jbutton.button == joystick_keymap.b_button) - tux.input.fire = DOWN; + tux.input.fire = true; 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.jump = UP; + tux.input.jump = false; else if (event.jbutton.button == joystick_keymap.b_button) - tux.input.fire = UP; + tux.input.fire = false; break; default: @@ -584,15 +459,101 @@ GameSession::process_events() } void +GameSession::handle_cheats() +{ + Player& tux = *currentsector->player; + + // 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(10000); + 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, "grid")) { + // toggle debug grid + debug_grid = !debug_grid; + 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.move(Vector( + (currentsector->solids->get_width()*32) - (screen->w*2), 0)); + currentsector->camera->reset( + Vector(tux.get_pos().x, tux.get_pos().y)); + last_keys.clear(); + } + if(compare_last(last_keys, "finish")) { + // finish current sector + exit_status = ES_LEVEL_FINISHED; + // don't add points to stats though... + } + // 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(); + } +} + +void GameSession::check_end_conditions() { Player* tux = currentsector->player; /* 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; @@ -769,12 +730,11 @@ GameSession::run() //frame_rate.update(); /* Handle time: */ - if (time_left.check() && currentsector->player->dying == DYING_NOT - && !end_sequence) + if (time_left.check() && !end_sequence) currentsector->player->kill(Player::KILL); /* Handle music: */ - if(currentsector->player->invincible_timer.check() && !end_sequence) + if (currentsector->player->invincible_timer.started() && !end_sequence) { currentsector->play_music(HERRING_MUSIC); } @@ -814,9 +774,16 @@ 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::start_sequence(const std::string& sequencename) { - if(sequencename == "endsequence") { + if(sequencename == "endsequence" || sequencename == "fireworks") { if(end_sequence) return; @@ -830,9 +797,11 @@ GameSession::start_sequence(const std::string& sequencename) global_stats.set_points(TIME_NEEDED_STAT, int(time_left.get_period() - time_left.get_timeleft())); - if(level->get_end_sequence_type() == Level::FIREWORKS_ENDSEQ_ANIM) { + if(sequencename == "fireworks") { currentsector->add_object(new Fireworks()); } + } else if(sequencename == "stoptux") { + end_sequence = ENDSEQUENCE_WAITING; } else { std::cout << "Unknown sequence '" << sequencename << "'.\n"; } @@ -854,7 +823,7 @@ GameSession::drawstatus(DrawingContext& context) LEFT_ALLIGN, LAYER_FOREGROUND1); } - if(time_left.check()) { + if(time_left.get_timeleft() < 0) { context.draw_text(white_text, _("TIME's UP"), Vector(screen->w/2, 0), CENTER_ALLIGN, LAYER_FOREGROUND1); } else if (time_left.get_timeleft() > TIME_WARNING @@ -905,12 +874,18 @@ GameSession::drawstatus(DrawingContext& context) } void -GameSession::drawresultscreen(void) +GameSession::drawresultscreen() { char str[80]; DrawingContext context; - currentsector->background->draw(context); + for(Sector::GameObjects::iterator i = currentsector->gameobjects.begin(); + i != currentsector->gameobjects.end(); ++i) { + Background* background = dynamic_cast (*i); + if(background) { + background->draw(context); + } + } context.draw_text(blue_text, _("Result:"), Vector(screen->w/2, 200), CENTER_ALLIGN, LAYER_FOREGROUND1); @@ -936,25 +911,21 @@ std::string slotinfo(int slot) stream << slot; slotfile = st_save_dir + "/slot" + stream.str() + ".stsg"; - lisp_object_t* savegame = lisp_read_from_file(slotfile.c_str()); - if (savegame) - { - LispReader reader(lisp_cdr(savegame)); - reader.read_string("title", title); - lisp_free(savegame); - } + try { + lisp::Parser parser; + std::auto_ptr root (parser.parse(slotfile)); - if (access(slotfile.c_str(), F_OK) == 0) - { - if (!title.empty()) - tmp = "Slot " + stream.str() + " - " + title; - else - tmp = "Slot " + stream.str() + " - Savegame"; - } - else - tmp = std::string(_("Slot")) + " " + stream.str() + " - " + std::string(_("Free")); + const lisp::Lisp* savegame = root->get_lisp("supertux-savegame"); + if(!savegame) + throw std::runtime_error("file is not a supertux-savegame."); + + savegame->get("title", title); + } catch(std::exception& e) { + return std::string(_("Slot")) + " " + stream.str() + " - " + + std::string(_("Free")); + } - return tmp; + return std::string("Slot ") + stream.str() + " - " + title; } bool process_load_game_menu() @@ -967,12 +938,6 @@ bool process_load_game_menu() 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...", @@ -981,7 +946,7 @@ bool process_load_game_menu() WorldMapNS::WorldMap worldmap; - worldmap.set_map_filename("icyisland.stwm"); + worldmap.set_map_filename("/levels/world1/worldmap.stwm"); // Load the game or at least set the savegame_file variable worldmap.loadgame(slotfile);