[Super-tux-commit] supertux/src gameloop.cpp,1.174,1.175 gameloop.h,1.59,1.60 level.cpp,1.99,1.100 M
Brought to you by:
wkendrick
Update of /cvsroot/super-tux/supertux/src In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv11135/src Modified Files: gameloop.cpp gameloop.h level.cpp Makefile.am scene.cpp scene.h sector.cpp worldmap.cpp worldmap.h Log Message: Implemented a statistics system. I believe this feature was originally requested by Ryan and the aim is to provide more replay value. Currently, it just keeps track of score. In future, it could keep track of other things like: min number of jumps, max number of enemies killed, min number of shots, min time needed, etc. When a better value is reached after playing the level again, it is replaced in the old statistics. Worldmap is the one in charge for saving statistics. TODO: draw current score and other stats of the current level in world map. I am thinking in drawing it in the Jump'n Bump way, that is using fade on text. I had to use LispWriter when saving a slot. Index: scene.cpp =================================================================== RCS file: /cvsroot/super-tux/supertux/src/scene.cpp,v retrieving revision 1.33 retrieving revision 1.34 diff -u -d -r1.33 -r1.34 --- scene.cpp 26 Jul 2004 18:09:14 -0000 1.33 +++ scene.cpp 14 Sep 2004 22:26:23 -0000 1.34 @@ -25,8 +25,7 @@ PlayerStatus player_status; PlayerStatus::PlayerStatus() - : score(0), - distros(0), + : distros(0), lives(START_LIVES), bonus(NO_BONUS), score_multiplier(1) @@ -35,7 +34,6 @@ void PlayerStatus::reset() { - score = 0; distros = 0; lives = START_LIVES; bonus = NO_BONUS; Index: Makefile.am =================================================================== RCS file: /cvsroot/super-tux/supertux/src/Makefile.am,v retrieving revision 1.41 retrieving revision 1.42 diff -u -d -r1.41 -r1.42 --- Makefile.am 29 Jul 2004 23:11:03 -0000 1.41 +++ Makefile.am 14 Sep 2004 22:26:23 -0000 1.42 @@ -14,7 +14,8 @@ scene.h special.cpp special.h supertux.cpp title.cpp title.h worldmap.cpp \ worldmap.h tile.h tile.cpp tile_manager.h tile_manager.cpp resources.h \ resources.cpp gameobjs.h gameobjs.cpp background.h background.cpp tilemap.h \ - tilemap.cpp serializable.h sector.cpp sector.h misc.h misc.cpp defines.h + tilemap.cpp serializable.h sector.cpp sector.h misc.h misc.cpp defines.h \ + statistics.cpp # EOF # INCLUDES = -I$(top_srcdir)/lib Index: sector.cpp =================================================================== RCS file: /cvsroot/super-tux/supertux/src/sector.cpp,v retrieving revision 1.24 retrieving revision 1.25 diff -u -d -r1.24 -r1.25 --- sector.cpp 14 Sep 2004 10:27:05 -0000 1.24 +++ sector.cpp 14 Sep 2004 22:26:23 -0000 1.25 @@ -40,6 +40,7 @@ #include "resources.h" #include "interactive_object.h" #include "door.h" +#include "statistics.h" Sector* Sector::_current = 0; @@ -653,7 +654,7 @@ void Sector::add_score(const Vector& pos, int s) { - player_status.score += s; + global_stats.add_points(SCORE_STAT, s); add_object(new FloatingScore(pos, s)); } @@ -779,9 +780,9 @@ counting_distros = false; solids->change_at(pos, tile->next_tile); } - + SoundManager::get()->play_sound(IDToSound(SND_DISTRO)); - player_status.score = player_status.score + SCORE_DISTRO; + global_stats.add_points(SCORE_STAT, SCORE_DISTRO); player_status.distros++; return true; } @@ -797,7 +798,7 @@ /* Get some score: */ SoundManager::get()->play_sound(IDToSound(SND_BRICK)); - player_status.score = player_status.score + SCORE_BRICK; + global_stats.add_points(SCORE_STAT, SCORE_BRICK); return true; } @@ -835,7 +836,7 @@ case 1: // Box with a distro! add_bouncy_distro(Vector(posx, posy)); SoundManager::get()->play_sound(IDToSound(SND_DISTRO)); - player_status.score = player_status.score + SCORE_DISTRO; + global_stats.add_points(SCORE_STAT, SCORE_DISTRO); player_status.distros++; break; @@ -900,7 +901,7 @@ (int)(pos.y / 32) * 32)); } - player_status.score = player_status.score + SCORE_DISTRO; + global_stats.add_points(SCORE_STAT, SCORE_DISTRO); player_status.distros++; } Index: gameloop.h =================================================================== RCS file: /cvsroot/super-tux/supertux/src/gameloop.h,v retrieving revision 1.59 retrieving revision 1.60 diff -u -d -r1.59 -r1.60 --- gameloop.h 13 Sep 2004 22:48:50 -0000 1.59 +++ gameloop.h 14 Sep 2004 22:26:13 -0000 1.60 @@ -86,6 +86,7 @@ // the sector and spawnpoint we shoudl spawn after this frame std::string newsector; std::string newspawnpoint; + public: enum ExitStatus { ES_NONE, ES_LEVEL_FINISHED, ES_GAME_OVER, ES_LEVEL_ABORT }; private: Index: level.cpp =================================================================== RCS file: /cvsroot/super-tux/supertux/src/level.cpp,v retrieving revision 1.99 retrieving revision 1.100 diff -u -d -r1.99 -r1.100 --- level.cpp 20 Jul 2004 18:04:47 -0000 1.99 +++ level.cpp 14 Sep 2004 22:26:22 -0000 1.100 @@ -156,4 +156,3 @@ return i->second; } - Index: worldmap.cpp =================================================================== RCS file: /cvsroot/super-tux/supertux/src/worldmap.cpp,v retrieving revision 1.115 retrieving revision 1.116 diff -u -d -r1.115 -r1.116 --- worldmap.cpp 8 Sep 2004 17:32:31 -0000 1.115 +++ worldmap.cpp 14 Sep 2004 22:26:23 -0000 1.116 @@ -28,6 +28,7 @@ #include "video/screen.h" #include "video/drawing_context.h" #include "utils/lispreader.h" +#include "utils/lispwriter.h" #include "special/frame_rate.h" #include "gameloop.h" #include "app/setup.h" @@ -512,7 +513,7 @@ reader.read_int("x", special_tile.x); reader.read_int("y", special_tile.y); - reader.read_string("level", special_tile.level_name, true); + reader.read_string("level", special_tile.level_name, false); special_tile.vertical_flip = false; reader.read_bool("vertical-flip", special_tile.vertical_flip); @@ -623,6 +624,18 @@ delete reader; } +void WorldMap::calculate_total_stats() +{ + total_stats.reset(); + for(SpecialTiles::iterator i = special_tiles.begin(); i != special_tiles.end(); ++i) + { + if (!i->level_name.empty() && i->solved) + { + total_stats += i->statistics; + } + } +} + void WorldMap::on_escape_press() { @@ -831,6 +844,10 @@ bool old_level_state = special_tile->solved; special_tile->solved = true; + // deal with statistics + special_tile->statistics.merge(global_stats); + calculate_total_stats(); + if (session.get_current_sector()->player->got_power != session.get_current_sector()->player->NONE_POWER) player_status.bonus = PlayerStatus::FLOWER_BONUS; @@ -870,7 +887,6 @@ level_finished = false; /* In case the player's abort the special_tile, keep it using the old status. But the minimum lives and no bonus. */ - player_status.score = old_player_status.score; player_status.distros = old_player_status.distros; player_status.lives = std::min(old_player_status.lives, player_status.lives); player_status.bonus = player_status.NO_BONUS; @@ -880,9 +896,9 @@ { level_finished = false; /* draw an end screen */ - /* in the future, this should make a dialog a la SuperMario, asking + /* TODO: in the future, this should make a dialog a la SuperMario, asking if the player wants to restart the world map with no score and from - special_tile 1 */ + level 1 */ char str[80]; DrawingContext context; @@ -892,7 +908,7 @@ context.draw_text_center(blue_text, _("GAMEOVER"), Vector(0, 200), LAYER_FOREGROUND1); - sprintf(str, _("SCORE: %d"), player_status.score); + sprintf(str, _("SCORE: %d"), total_stats.get_points(SCORE_STAT)); context.draw_text_center(gold_text, str, Vector(0, 230), LAYER_FOREGROUND1); @@ -1047,7 +1063,7 @@ WorldMap::draw_status(DrawingContext& context) { char str[80]; - sprintf(str, " %d", player_status.score); + sprintf(str, " %d", total_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); @@ -1174,38 +1190,60 @@ return; std::cout << "savegame: " << filename << std::endl; - std::ofstream out(filename.c_str()); - int nb_solved_levels = 0; + std::ofstream file(filename.c_str(), std::ios::out); + LispWriter* writer = new LispWriter(file); + + int nb_solved_levels = 0, total_levels = 0; for(SpecialTiles::iterator i = special_tiles.begin(); i != special_tiles.end(); ++i) { + if(!i->level_name.empty()) + ++total_levels; if (i->solved) ++nb_solved_levels; } + char nb_solved_levels_str[80], total_levels_str[80]; + sprintf(nb_solved_levels_str, "%d", nb_solved_levels); + sprintf(total_levels_str, "%d", total_levels); + + writer->write_comment("Worldmap save file"); + + writer->start_list("supertux-savegame"); + + writer->write_int("version", 1); + writer->write_string("title", std::string(name + " - " + nb_solved_levels_str + "/" + total_levels_str)); + writer->write_string("map", map_filename); + writer->write_int("lives", player_status.lives); + writer->write_int("distros", player_status.lives); + + writer->start_list("tux"); + + writer->write_float("x", tux->get_tile_pos().x); + writer->write_float("y", tux->get_tile_pos().y); + writer->write_string("back", direction_to_string(tux->back_direction)); + writer->write_string("bonus", bonus_to_string(player_status.bonus)); + + writer->end_list("tux"); + + writer->start_list("levels"); - out << "(supertux-savegame\n" - << " (version 1)\n" - << " (title \"" << name << " - " << nb_solved_levels << "/" << special_tiles.size() << "\")\n" - << " (map \"" << map_filename << "\")\n" - << " (lives " << player_status.lives << ")\n" - << " (score " << player_status.score << ")\n" - << " (distros " << player_status.distros << ")\n" - << " (tux (x " << tux->get_tile_pos().x << ") (y " << tux->get_tile_pos().y << ")\n" - << " (back \"" << direction_to_string(tux->back_direction) << "\")\n" - << " (bonus \"" << bonus_to_string(player_status.bonus) << "\"))\n" - << " (levels\n"; - for(SpecialTiles::iterator i = special_tiles.begin(); i != special_tiles.end(); ++i) { if (i->solved && !i->level_name.empty()) { - out << " (level (name \"" << i->level_name << "\")\n" - << " (solved #t))\n"; + writer->start_list("level"); + + writer->write_string("name", i->level_name); + writer->write_bool("solved", true); + i->statistics.write(*writer); + + writer->end_list("level"); } } - out << " )\n" - << " )\n\n;; EOF ;;" << std::endl; + writer->end_list("levels"); + + writer->end_list("supertux-savegame"); } void @@ -1245,7 +1283,6 @@ load_map(); reader.read_int("lives", player_status.lives); - reader.read_int("score", player_status.score); reader.read_int("distros", player_status.distros); if (player_status.lives < 0) @@ -1283,13 +1320,17 @@ bool solved = false; LispReader level_reader(data); - level_reader.read_string("name", name, true); + level_reader.read_string("name", name); level_reader.read_bool("solved", solved); for(SpecialTiles::iterator i = special_tiles.begin(); i != special_tiles.end(); ++i) { if (name == i->level_name) + { i->solved = solved; + i->statistics.parse(level_reader); + break; + } } } @@ -1298,6 +1339,8 @@ } lisp_free(savegame); + + calculate_total_stats(); } void Index: scene.h =================================================================== RCS file: /cvsroot/super-tux/supertux/src/scene.h,v retrieving revision 1.33 retrieving revision 1.34 diff -u -d -r1.33 -r1.34 --- scene.h 20 Jul 2004 18:04:48 -0000 1.33 +++ scene.h 14 Sep 2004 22:26:23 -0000 1.34 @@ -28,7 +28,6 @@ // Player stats struct PlayerStatus { - int score; int distros; int lives; enum BonusType { NO_BONUS, GROWUP_BONUS, FLOWER_BONUS }; Index: worldmap.h =================================================================== RCS file: /cvsroot/super-tux/supertux/src/worldmap.h,v retrieving revision 1.45 retrieving revision 1.46 diff -u -d -r1.45 -r1.46 --- worldmap.h 26 Aug 2004 23:05:03 -0000 1.45 +++ worldmap.h 14 Sep 2004 22:26:23 -0000 1.46 @@ -26,6 +26,7 @@ #include "math/vector.h" #include "audio/musicref.h" #include "video/screen.h" +#include "statistics.h" extern Menu* worldmap_menu; @@ -159,6 +160,9 @@ std::string title; bool solved; + /** Statistics for level tiles */ + Statistics statistics; + /** Optional flags: */ /** Check if this level should be vertically flipped */ @@ -220,6 +224,12 @@ void get_level_title(SpecialTile& special_tile); void draw_status(DrawingContext& context); + + // to avoid calculating total stats all the time. This way only + // when need, it is calculated. + Statistics total_stats; + void calculate_total_stats(); + public: WorldMap(); ~WorldMap(); Index: gameloop.cpp =================================================================== RCS file: /cvsroot/super-tux/supertux/src/gameloop.cpp,v retrieving revision 1.174 retrieving revision 1.175 diff -u -d -r1.174 -r1.175 --- gameloop.cpp 14 Sep 2004 10:40:28 -0000 1.174 +++ gameloop.cpp 14 Sep 2004 22:26:08 -0000 1.175 @@ -61,6 +61,7 @@ #include "intro.h" #include "misc.h" #include "camera.h" +#include "statistics.h" GameSession* GameSession::current_ = 0; @@ -150,6 +151,8 @@ levelintro(); } + global_stats.reset(); + time_left.init(true); start_timers(); currentsector->play_music(LEVEL_MUSIC); @@ -785,7 +788,7 @@ { char str[60]; - snprintf(str, 60, " %d", player_status.score); + 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); @@ -855,7 +858,7 @@ context.draw_text_center(blue_text, _("Result:"), Vector(0, 200), LAYER_FOREGROUND1); - sprintf(str, _("SCORE: %d"), player_status.score); + sprintf(str, _("SCORE: %d"), global_stats.get_points(SCORE_STAT)); context.draw_text_center(gold_text, str, Vector(0, 224), LAYER_FOREGROUND1); sprintf(str, _("COINS: %d"), player_status.distros); |