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();