From 3480562b7855ef8702ac7bffc00c3eb6a7947075 Mon Sep 17 00:00:00 2001 From: hikerstk Date: Thu, 2 Sep 2010 13:14:07 +0000 Subject: [PATCH] Added a new object in the world hierarchy (WorldWithRank) which contains all codes related to ranking the karts (which is used to display the icons in the race gui and the end result table). The battle mode should now be fixed, but follow-the-leader has still issues and will most likely crash at the end. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@5864 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/Makefile.am | 2 + src/ide/vc9/supertuxkart.vcproj | 8 ++ src/modes/follow_the_leader.cpp | 40 ++++---- src/modes/follow_the_leader.hpp | 2 +- src/modes/linear_world.cpp | 66 +------------- src/modes/linear_world.hpp | 22 ++--- src/modes/three_strikes_battle.cpp | 29 ++---- src/modes/three_strikes_battle.hpp | 12 +-- src/modes/world.hpp | 6 -- src/modes/world_with_rank.cpp | 91 +++++++++++++++++++ src/modes/world_with_rank.hpp | 56 ++++++++++++ .../dialogs/race_over_dialog.cpp | 5 +- src/states_screens/race_result_gui.cpp | 8 +- 13 files changed, 209 insertions(+), 138 deletions(-) create mode 100644 src/modes/world_with_rank.cpp create mode 100755 src/modes/world_with_rank.hpp diff --git a/src/Makefile.am b/src/Makefile.am index 58e02d9d4..2ad7a67fb 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -198,6 +198,8 @@ supertuxkart_SOURCES = \ modes/world.hpp \ modes/world_status.cpp \ modes/world_status.hpp \ + modes/world_with_rank.cpp \ + modes/world_with_rank.hpp \ network/character_confirm_message.hpp \ network/character_info_message.hpp \ network/character_selected_message.hpp \ diff --git a/src/ide/vc9/supertuxkart.vcproj b/src/ide/vc9/supertuxkart.vcproj index 0ec6fa047..a4ffec1b5 100644 --- a/src/ide/vc9/supertuxkart.vcproj +++ b/src/ide/vc9/supertuxkart.vcproj @@ -502,6 +502,10 @@ RelativePath="..\..\modes\world_status.cpp" > + + + + *order) { - const unsigned int NUM_KARTS = getNumKarts(); - - int *scores = new int[NUM_KARTS]; - double *race_time = new double[NUM_KARTS]; + const unsigned int num_karts = getNumKarts(); + order->resize(num_karts); + + int *scores = new int[num_karts]; + double *race_time = new double[num_karts]; World *world = World::getWorld(); // Ignore kart 0, since it was the leader - order[0] = -1; - for( unsigned int kart_id = 1; kart_id < NUM_KARTS; ++kart_id ) + (*order)[0] = -1; + for( unsigned int kart_id = 1; kart_id < num_karts; ++kart_id ) { - order[kart_id] = kart_id; + (*order)[kart_id] = kart_id; scores[kart_id] = race_manager->getKartScore(kart_id); race_time[kart_id] = race_manager->getOverallTime(kart_id); @@ -172,22 +173,25 @@ void FollowTheLeaderRace::raceResultOrder( int* order ) do { sorted = true; - for( unsigned int i = 1; i < NUM_KARTS - 1; ++i ) + for( unsigned int i = 1; i < num_karts - 1; ++i ) { - if( scores[order[i]] < scores[order[i+1]] || - (scores[order[i]] == scores[order[i+1]] - && race_time[order[i]] > race_time[order[i+1]]) ) + if( scores[(*order)[i]] < scores[(*order)[i+1]] || + (scores[(*order)[i]] == scores[(*order)[i+1]] + && race_time[(*order)[i]] > race_time[(*order)[i+1]]) ) { - int tmp = order[i]; - order[i] = order[i+1]; - order[i+1] = tmp; - sorted = false; + int tmp = (*order)[i]; + (*order)[i] = (*order)[i+1]; + (*order)[i+1] = tmp; + sorted = false; } } } while(!sorted); - for(unsigned int i=1; igetKart(order[i])->setPosition(i); + for(unsigned int i=1; igetKart((*order)[i])->setPosition(i); + setKartPosition((*order)[i], i); + } delete []scores; delete []race_time; diff --git a/src/modes/follow_the_leader.hpp b/src/modes/follow_the_leader.hpp index 9903225c8..0cfd4d25f 100644 --- a/src/modes/follow_the_leader.hpp +++ b/src/modes/follow_the_leader.hpp @@ -49,7 +49,7 @@ public: /** Called by the race result GUI at the end of the race to know the final order (fill in the 'order' array) */ - virtual void raceResultOrder( int* order ); + virtual void getRaceResultOrder(std::vector *order); }; diff --git a/src/modes/linear_world.cpp b/src/modes/linear_world.cpp index 5701863e9..f71f50281 100644 --- a/src/modes/linear_world.cpp +++ b/src/modes/linear_world.cpp @@ -34,7 +34,7 @@ /** Constructs the linear world. Note that here no functions can be called * that use World::getWorld(), since it is not yet defined. */ -LinearWorld::LinearWorld() : World() +LinearWorld::LinearWorld() : WorldWithRank() { m_kart_display_info = NULL; m_last_lap_sfx = sfx_manager->createSoundSource("lastlap"); @@ -48,15 +48,13 @@ LinearWorld::LinearWorld() : World() */ void LinearWorld::init() { - World::init(); + WorldWithRank::init(); m_last_lap_sfx_played = false; const unsigned int kart_amount = m_karts.size(); - m_position_index.resize(kart_amount); m_kart_display_info = new RaceGUIBase::KartIconDisplayInfo[kart_amount]; for(unsigned int n=0; ngetStatus()== SFXManager::SFX_PLAYING) // m_last_lap_sfx->stop(); m_last_lap_sfx_played = false; @@ -169,7 +167,7 @@ void LinearWorld::update(float delta) { // run generic parent stuff that applies to all modes. It // especially updates the kart positions. - World::update(delta); + WorldWithRank::update(delta); const unsigned int kart_amount = getNumKarts(); @@ -487,60 +485,6 @@ RaceGUIBase::KartIconDisplayInfo* LinearWorld::getKartsDisplayInfo() return m_kart_display_info; } // getKartsDisplayInfo -// ---------------------------------------------------------------------------- -/** Sets up the mapping from kart position to kart index. - */ -void LinearWorld::raceResultOrder(std::vector *order) -{ - const unsigned int NUM_KARTS = getNumKarts(); - order->resize(NUM_KARTS); - -#ifndef NDEBUG - for (unsigned int i=0; i < NUM_KARTS; i++) - { - (*order)[i] = -1; - } - - bool positions_ok = true; -#endif - - for (unsigned int i=0; i < NUM_KARTS; i++) - { - const int position = getKart(i)->getPosition()-1; - -#ifndef NDEBUG - // sanity checks - if ((*order)[position] != -1) - { - std::cerr << "== TWO KARTS ARE BEING GIVEN THE SAME POSITION!! ==\n"; - for (unsigned int j=0; j < NUM_KARTS; j++) - { - if ((*order)[j] == -1) - { - std::cout << " No kart is yet set at position " << j << std::endl; - } - else - { - std::cout << " Kart " << (*order)[j] << " is at position " << j << std::endl; - } - } - std::cout << "Kart " << i << " is being given posiiton " << (getKart(i)->getPosition()-1) - << ", but this position is already taken\n"; - positions_ok = false; - } -#endif - - // actually assign the position - (*order)[position] = i; // even for eliminated karts - } - -#ifndef NDEBUG - if (!positions_ok) history->Save(); - assert(positions_ok); -#endif - -} // raceResultOrder - //----------------------------------------------------------------------------- /** Estimate the arrival time of any karts that haven't arrived yet by using * their average speed up to now and the distance still to race. This @@ -746,7 +690,7 @@ void LinearWorld::updateRacePosition() #endif kart->setPosition(p); - m_position_index[p-1] = i; + setKartPosition(i, p); // Switch on faster music if not already done so, if the // first kart is doing its last lap, and if the estimated // remaining time is less than 30 seconds. diff --git a/src/modes/linear_world.hpp b/src/modes/linear_world.hpp index c2be872f6..db574e9e7 100644 --- a/src/modes/linear_world.hpp +++ b/src/modes/linear_world.hpp @@ -20,7 +20,7 @@ #include -#include "modes/world.hpp" +#include "modes/world_with_rank.hpp" class SFXBase; @@ -30,7 +30,7 @@ class SFXBase; * and lap counting. * \ingroup modes */ -class LinearWorld : public World +class LinearWorld : public WorldWithRank { /** Sfx for the final lap. */ SFXBase *m_last_lap_sfx; @@ -61,9 +61,6 @@ private: }; - /** This contains a mapping from race position to kart index. */ - std::vector m_position_index; - protected: RaceGUIBase::KartIconDisplayInfo* m_kart_display_info; @@ -84,11 +81,12 @@ protected: public: LinearWorld(); - /** call just after instanciating. can't be moved to the contructor as child - classes must be instanciated, otherwise polymorphism will fail and the - results will be incorrect */ - void init(); + /** call just after instanciating. can't be moved to the contructor as child + classes must be instanciated, otherwise polymorphism will fail and the + results will be incorrect */ + virtual void init(); virtual ~LinearWorld(); + virtual void update(float delta); int getSectorForKart(const int kart_id) const; float getDistanceDownTrackForKart(const int kart_id) const; @@ -101,9 +99,6 @@ public: virtual RaceGUIBase::KartIconDisplayInfo* getKartsDisplayInfo(); virtual void moveKartAfterRescue(Kart* kart); - /** Returns the kart with position p, 1<=p<=num_karts). */ - const Kart* getKartAtPosition(unsigned int p) const - { return m_karts[m_position_index[p-1]]; } virtual void restartRace(); virtual bool raceHasLaps(){ return true; } @@ -111,9 +106,6 @@ public: virtual bool haveBonusBoxes(){ return true; } - /** Called by the race result GUI at the end of the race to know the final order - (fill in the 'order' array) */ - virtual void raceResultOrder(std::vector *order); /** Returns true if the kart is on a valid driveline quad. * \param kart_index Index of the kart. */ diff --git a/src/modes/three_strikes_battle.cpp b/src/modes/three_strikes_battle.cpp index 650c0900c..ce398b9f0 100644 --- a/src/modes/three_strikes_battle.cpp +++ b/src/modes/three_strikes_battle.cpp @@ -25,17 +25,17 @@ //----------------------------------------------------------------------------- -ThreeStrikesBattle::ThreeStrikesBattle() : World() +ThreeStrikesBattle::ThreeStrikesBattle() : WorldWithRank() { WorldStatus::setClockMode(CLOCK_CHRONO); m_use_highscores = false; -} +} // ThreeStrikesBattle //----------------------------------------------------------------------------- void ThreeStrikesBattle::init() { - World::init(); + WorldWithRank::init(); // check for possible problems if AI karts were incorrectly added if(getNumKarts() > race_manager->getNumPlayers()) @@ -163,6 +163,7 @@ void ThreeStrikesBattle::updateKartRanks() for( unsigned int n = 0; n < NUM_KARTS; ++n ) { m_karts[ karts_list[n] ]->setPosition( n+1 ); + setKartPosition(karts_list[n], n+1); } delete [] karts_list; } // updateKartRank @@ -183,13 +184,13 @@ bool ThreeStrikesBattle::isRaceOver() void ThreeStrikesBattle::terminateRace() { updateKartRanks(); - World::terminateRace(); + WorldWithRank::terminateRace(); } // terminateRace //----------------------------------------------------------------------------- void ThreeStrikesBattle::restartRace() { - World::restartRace(); + WorldWithRank::restartRace(); const unsigned int kart_amount = m_karts.size(); @@ -319,21 +320,3 @@ void ThreeStrikesBattle::moveKartAfterRescue(Kart* kart) //add hit to kart kartHit(kart->getWorldKartId()); } // moveKartAfterRescue - -//----------------------------------------------------------------------------- -void ThreeStrikesBattle::raceResultOrder(std::vector *order) -{ - updateKartRanks(); - - const unsigned int num_karts = getNumKarts(); - order->resize(num_karts); - for (unsigned int i=0; i < num_karts; i++) (*order)[i] = -1; - - for( unsigned int kart_id = 0; kart_id < num_karts; ++kart_id ) - { - const int pos = m_karts[kart_id]->getPosition() - 1; - assert(pos >= 0); - assert(pos < (int)num_karts); - (*order)[pos] = kart_id; - } -} // raceResultOrder diff --git a/src/modes/three_strikes_battle.hpp b/src/modes/three_strikes_battle.hpp index 923de376e..3b71b7a38 100644 --- a/src/modes/three_strikes_battle.hpp +++ b/src/modes/three_strikes_battle.hpp @@ -1,4 +1,4 @@ -// $Id: world.hpp 2326 2008-10-04 18:50:45Z auria $ +// $Id: three_strikes_battle.hpp 2326 2008-10-04 18:50:45Z auria $ // // SuperTuxKart - a fun racing game with go-kart // Copyright (C) 2004 SuperTuxKart-Team @@ -22,14 +22,14 @@ #include -#include "modes/world.hpp" +#include "modes/world_with_rank.hpp" #include "states_screens/race_gui_base.hpp" /** * \brief An implementation of World, to provide the 3 strikes battle game mode * \ingroup modes */ -class ThreeStrikesBattle : public World +class ThreeStrikesBattle : public WorldWithRank { private: struct BattleInfo @@ -74,11 +74,7 @@ public: virtual std::string getIdent() const; virtual void kartHit(const int kart_id); - - /** Called by the race result GUI at the end of the race to know the final order - (fill in the 'order' array) */ - virtual void raceResultOrder(std::vector *order); - + void updateKartRanks(); }; // ThreeStrikesBattles diff --git a/src/modes/world.hpp b/src/modes/world.hpp index 530d4e9fe..09f8aacd3 100644 --- a/src/modes/world.hpp +++ b/src/modes/world.hpp @@ -248,12 +248,6 @@ public: */ virtual void kartHit(const int kart_id) {}; - /** Called by the race result GUI at the end of the race to know the final order - * \param[out] order returns the order of karts. order[0] will contain the ID of - * the first kart, order[1] the ID of the second kart, etc... - * Array dimension must be the number of karts. - */ - virtual void raceResultOrder(std::vector *order ) = 0; bool clearBackBuffer() const { return m_clear_back_buffer; } const irr::video::SColor& getClearColor() const { return m_clear_color; } diff --git a/src/modes/world_with_rank.cpp b/src/modes/world_with_rank.cpp new file mode 100644 index 000000000..f98f2b72e --- /dev/null +++ b/src/modes/world_with_rank.cpp @@ -0,0 +1,91 @@ +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2010 Joerg Henrichs +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// 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 "modes/world_with_rank.hpp" + +#include "race/history.hpp" + +//----------------------------------------------------------------------------- +void WorldWithRank::init() +{ + World::init(); + m_position_index.resize(m_karts.size()); +} // init + +//----------------------------------------------------------------------------- +void WorldWithRank::setKartPosition(unsigned int kart_id, + unsigned int position) +{ + m_position_index[position-1] = kart_id; +} // setKartPosition + +// ---------------------------------------------------------------------------- +/** Called by the race result GUI at the end of the race to know the final + * order. + * \param[out] order returns the order of karts. order[0] will contain the ID + * of the first kart, order[1] the ID of the second kart, + * etc... Array dimension will be adjusted to the number of + * karts. + */ +void WorldWithRank::getRaceResultOrder(std::vector *order) +{ + const unsigned int num_karts = getNumKarts(); + order->resize(num_karts); + +#ifndef NDEBUG + for (unsigned int i=0; i < num_karts; i++) (*order)[i] = -1; + + bool positions_ok = true; +#endif + + for (unsigned int i=0; i < num_karts; i++) + { + const int position = getKart(i)->getPosition()-1; + +#ifndef NDEBUG + // sanity checks + if ((*order)[position] != -1) + { + std::cerr << "== TWO KARTS ARE BEING GIVEN THE SAME POSITION!! ==\n"; + for (unsigned int j=0; j < num_karts; j++) + { + if ((*order)[j] == -1) + { + std::cout << " No kart is yet set at position " << j << std::endl; + } + else + { + std::cout << " Kart " << (*order)[j] << " is at position " << j << std::endl; + } + } + std::cout << "Kart " << i << " is being given posiiton " << (getKart(i)->getPosition()-1) + << ", but this position is already taken\n"; + positions_ok = false; + } +#endif + + // actually assign the position + (*order)[position] = i; // even for eliminated karts + } + +#ifndef NDEBUG + if (!positions_ok) history->Save(); + assert(positions_ok); +#endif + +} // getRaceResultOrder + diff --git a/src/modes/world_with_rank.hpp b/src/modes/world_with_rank.hpp new file mode 100755 index 000000000..12539db4c --- /dev/null +++ b/src/modes/world_with_rank.hpp @@ -0,0 +1,56 @@ +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2010 Joerg Henrichs +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// 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. + +#ifndef HEADER_WORLD_WITH_RANK_HPP +#define HEADER_WORLD_WITH_RANK_HPP + +#include + +#include "modes/world.hpp" + +/** + * A WorldWithRank is a world where the karts are ranked. This is the base + * class for races and battle modes - all of which rank the kart. + * A class using this as a subclass must call setKartRank(kart id, rank) + * and this class is used to access the ranks from other objects. + * \ingroup modes + */ +class WorldWithRank : public World +{ +private: + /** This contains a mapping from race position to kart index. */ + std::vector m_position_index; +public: + WorldWithRank() : World() {} + /** call just after instanciating. can't be moved to the contructor as child + classes must be instanciated, otherwise polymorphism will fail and the + results will be incorrect */ + virtual void init(); + + void setKartPosition(unsigned int kart_id, + unsigned int position); + + /** Returns the kart with position p, 1<=p<=num_karts). */ + const Kart* getKartAtPosition(unsigned int p) const + { return m_karts[m_position_index[p-1]]; } + + /** Called by the race result GUI at the end of the race to know the + * final order (fill in the 'order' array) */ + virtual void getRaceResultOrder(std::vector *order); +}; // WorldWithRank + +#endif diff --git a/src/states_screens/dialogs/race_over_dialog.cpp b/src/states_screens/dialogs/race_over_dialog.cpp index 45e922fa0..02b4db0c0 100644 --- a/src/states_screens/dialogs/race_over_dialog.cpp +++ b/src/states_screens/dialogs/race_over_dialog.cpp @@ -27,6 +27,7 @@ #include "karts/kart_properties_manager.hpp" #include "modes/three_strikes_battle.hpp" #include "modes/world.hpp" +#include "modes/world_with_rank.hpp" #include "network/network_manager.hpp" #include "race/race_manager.hpp" #include "states_screens/feature_unlocked.hpp" @@ -106,10 +107,10 @@ RaceOverDialog::RaceOverDialog(const float percentWidth, caption->setTabStop(false); caption->setTextAlignment(EGUIA_CENTER, EGUIA_CENTER); - World *world = World::getWorld(); + WorldWithRank *world = (WorldWithRank*)World::getWorld(); const unsigned int num_karts = world->getNumKarts(); std::vector order; - world->raceResultOrder(&order); + world->getRaceResultOrder(&order); const bool display_time = (world->getClockMode() == WorldStatus::CLOCK_CHRONO); diff --git a/src/states_screens/race_result_gui.cpp b/src/states_screens/race_result_gui.cpp index ddd3a961f..5cf8bc17e 100644 --- a/src/states_screens/race_result_gui.cpp +++ b/src/states_screens/race_result_gui.cpp @@ -23,7 +23,7 @@ #include "guiengine/engine.hpp" #include "guiengine/scalable_font.hpp" #include "guiengine/widget.hpp" -#include "modes/world.hpp" +#include "modes/world_with_rank.hpp" #include "states_screens/dialogs/race_over_dialog.hpp" #include "states_screens/main_menu_screen.hpp" #include "states_screens/race_setup_screen.hpp" @@ -215,10 +215,10 @@ void RaceResultGUI::determineTableLayout() assert(m_font); m_was_monospace = m_font->getMonospaceDigits(); m_font->setMonospaceDigits(true); - World *world = World::getWorld(); + WorldWithRank *rank_world = (WorldWithRank*)World::getWorld(); std::vector order; - world->raceResultOrder(&order); + rank_world->getRaceResultOrder(&order); m_all_row_infos.resize(order.size()); @@ -239,7 +239,7 @@ void RaceResultGUI::determineTableLayout() // Save a pointer to the current row_info entry RowInfo *ri = &(m_all_row_infos[num_karts]); num_karts++; - Kart *kart = world->getKart(order[i]); + Kart *kart = rank_world->getKart(order[i]); ri->m_is_player_kart = kart->getController()->isPlayerController(); ri->m_kart_name = kart->getName();