diff --git a/src/modes/free_for_all.cpp b/src/modes/free_for_all.cpp index 91ab8dafe8a..204b0bc0cf4 100644 --- a/src/modes/free_for_all.cpp +++ b/src/modes/free_for_all.cpp @@ -226,6 +226,46 @@ void FreeForAll::getKartsDisplayInfo( } } // getKartsDisplayInfo +//----------------------------------------------------------------------------- +std::pair FreeForAll::getSpeedometerDigit( + const AbstractKart *kart) const +{ + if (kart->isEliminated()) // m_scores[id] is INT_MIN + { + return std::make_pair(0, video::SColor(255, 128, 128, 128)); + } + + int id = kart->getWorldKartId(); + + // Fade from green to red + std::vector sorted_scores; + for (int i = 0; i < m_scores.size(); i++) + { + if (!getKart(i)->isEliminated()) + { + sorted_scores.push_back(m_scores[i]); + } + } + std::sort(sorted_scores.begin(), sorted_scores.end(), std::greater()); + + if (sorted_scores.size() == 1) + { + int s = sorted_scores[id]; + video::SColor color = video::SColor(255, s <= 0 ? 255 : 0, s >= 0 ? 255 : 0, 0); + return std::make_pair(s, color); + } + + int rank = std::lower_bound( + sorted_scores.begin(), sorted_scores.end(), + m_scores[id], std::greater()) - sorted_scores.begin(); + + float value = (float)rank / (sorted_scores.size() - 1); + int r = std::min(int(value * 510), 255); + int g = std::min(int((1.0 - value) * 510), 255); + + return std::make_pair(m_scores[id], video::SColor(255, r, g, 0)); +} // getSpeedometerDigit + // ---------------------------------------------------------------------------- void FreeForAll::terminateRace() { diff --git a/src/modes/free_for_all.hpp b/src/modes/free_for_all.hpp index ea772443061..39fccca6f5e 100644 --- a/src/modes/free_for_all.hpp +++ b/src/modes/free_for_all.hpp @@ -55,6 +55,11 @@ class FreeForAll : public WorldWithRank // ------------------------------------------------------------------------ virtual bool raceHasLaps() OVERRIDE { return false; } // ------------------------------------------------------------------------ + virtual bool shouldDrawSpeedometerDigit() const OVERRIDE { return true; } + // ------------------------------------------------------------------------ + virtual std::pair + getSpeedometerDigit(const AbstractKart *kart) const OVERRIDE; + // ------------------------------------------------------------------------ virtual const std::string& getIdent() const OVERRIDE; // ------------------------------------------------------------------------ virtual bool kartHit(int kart_id, int hitter = -1) OVERRIDE; diff --git a/src/modes/three_strikes_battle.cpp b/src/modes/three_strikes_battle.cpp index 4029f68aaf3..c4f4c7982f9 100644 --- a/src/modes/three_strikes_battle.cpp +++ b/src/modes/three_strikes_battle.cpp @@ -538,6 +538,30 @@ void ThreeStrikesBattle::getKartsDisplayInfo( } } // getKartsDisplayInfo +//----------------------------------------------------------------------------- +std::pair ThreeStrikesBattle::getSpeedometerDigit( + const AbstractKart *kart) const +{ + video::SColor color = video::SColor(255, 255, 255, 255); + int id = kart->getWorldKartId(); + switch(m_kart_info[id].m_lives) + { + case 3: + color = video::SColor(255, 0, 255, 0); + break; + case 2: + color = video::SColor(255, 255, 229, 0); + break; + case 1: + color = video::SColor(255, 255, 0, 0); + break; + case 0: + color = video::SColor(255, 128, 128, 128); + break; + } + return std::make_pair(m_kart_info[id].m_lives, color); +} // getSpeedometerDigit + //----------------------------------------------------------------------------- void ThreeStrikesBattle::enterRaceOverState() { diff --git a/src/modes/three_strikes_battle.hpp b/src/modes/three_strikes_battle.hpp index 95f25dbe7d1..d9886760f51 100644 --- a/src/modes/three_strikes_battle.hpp +++ b/src/modes/three_strikes_battle.hpp @@ -121,6 +121,11 @@ class ThreeStrikesBattle : public WorldWithRank // ------------------------------------------------------------------------ virtual bool raceHasLaps() OVERRIDE { return false; } // ------------------------------------------------------------------------ + virtual bool shouldDrawSpeedometerDigit() const OVERRIDE { return true; } + // ------------------------------------------------------------------------ + virtual std::pair + getSpeedometerDigit(const AbstractKart *kart) const OVERRIDE; + // ------------------------------------------------------------------------ virtual const std::string& getIdent() const OVERRIDE; // ------------------------------------------------------------------------ virtual bool kartHit(int kart_id, int hitter = -1) OVERRIDE; diff --git a/src/modes/world.hpp b/src/modes/world.hpp index eb76b941e08..4351810bd6e 100644 --- a/src/modes/world.hpp +++ b/src/modes/world.hpp @@ -375,6 +375,13 @@ class World : public WorldStatus virtual bool shouldDrawTimer() const { return isActiveRacePhase() && getClockMode() != CLOCK_NONE; } // ------------------------------------------------------------------------ + /** \return whether this world should draw the digit on the center of speedometer */ + virtual bool shouldDrawSpeedometerDigit() const { return false; } + // ------------------------------------------------------------------------ + /** \return a pair consists of the digit and the color of the digit */ + virtual std::pair getSpeedometerDigit(const AbstractKart *kart) const + { return std::make_pair(0, video::SColor(255, 255, 255, 255)); } + // ------------------------------------------------------------------------ /** \return whether this world can generate/have highscores */ bool useHighScores() const { return m_use_highscores; } // ------------------------------------------------------------------------ diff --git a/src/modes/world_with_rank.cpp b/src/modes/world_with_rank.cpp index 30bfee10f93..4f154feffb5 100644 --- a/src/modes/world_with_rank.cpp +++ b/src/modes/world_with_rank.cpp @@ -85,6 +85,12 @@ AbstractKart* WorldWithRank::getKartAtPosition(unsigned int p) const return m_karts[m_position_index[p-1]].get(); } // getKartAtPosition +//----------------------------------------------------------------------------- +std::pair WorldWithRank::getSpeedometerDigit(const AbstractKart *kart) const +{ + return std::make_pair(kart->getPosition(), video::SColor(255, 255, 255, 255)); +} // getSpeedometerDigit + //----------------------------------------------------------------------------- /** This function must be called before starting to set all kart positions * again. It's mainly used to add some debug support, i.e. detect if the diff --git a/src/modes/world_with_rank.hpp b/src/modes/world_with_rank.hpp index 3b6f7e87def..1329d3cdf00 100644 --- a/src/modes/world_with_rank.hpp +++ b/src/modes/world_with_rank.hpp @@ -76,7 +76,10 @@ class WorldWithRank : public World virtual void init() OVERRIDE; virtual void reset(bool restart=false) OVERRIDE; - bool displayRank() const { return m_display_rank; } + virtual bool shouldDrawSpeedometerDigit() const OVERRIDE + { return m_display_rank; } + virtual std::pair + getSpeedometerDigit(const AbstractKart *kart) const OVERRIDE; void beginSetKartPositions(); bool setKartPosition(unsigned int kart_id, diff --git a/src/states_screens/race_gui.cpp b/src/states_screens/race_gui.cpp index a57a852d7e6..cf6940d0b31 100644 --- a/src/states_screens/race_gui.cpp +++ b/src/states_screens/race_gui.cpp @@ -148,13 +148,10 @@ RaceGUI::~RaceGUI() void RaceGUI::init() { RaceGUIBase::init(); - // Technically we only need getNumLocalPlayers, but using the - // global kart id to find the data for a specific kart. - int n = RaceManager::get()->getNumberOfKarts(); - m_animation_states.resize(n); - m_rank_animation_duration.resize(n); - m_last_ranks.resize(n); + m_animation_states.clear(); + m_animation_duration.clear(); + m_last_digit.clear(); } // init //----------------------------------------------------------------------------- @@ -164,11 +161,10 @@ void RaceGUI::init() void RaceGUI::reset() { RaceGUIBase::reset(); - for(unsigned int i=0; igetNumberOfKarts(); i++) - { - m_animation_states[i] = AS_NONE; - m_last_ranks[i] = i+1; - } + + m_animation_states.clear(); + m_animation_duration.clear(); + m_last_digit.clear(); } // reset //----------------------------------------------------------------------------- @@ -908,49 +904,59 @@ void RaceGUI::drawRank(const AbstractKart *kart, float min_ratio, int meter_width, int meter_height, float dt) { - static video::SColor color = video::SColor(255, 255, 255, 255); - // Draw rank - WorldWithRank *world = dynamic_cast(World::getWorld()); - if (!world || !world->displayRank()) + World *world = World::getWorld(); + if (!world || !world->shouldDrawSpeedometerDigit()) return; + std::pair digit_data = world->getSpeedometerDigit(kart); + + int number = digit_data.first; + video::SColor color = digit_data.second; + int id = kart->getWorldKartId(); + if (m_animation_states.find(id) == m_animation_states.end()) + { + m_animation_duration[id] = 0.0f; + m_animation_states[id] = AS_NONE; + m_last_digit[id] = number; + } + if (m_animation_states[id] == AS_NONE) { - if (m_last_ranks[id] != kart->getPosition()) + if (m_last_digit[id] != number) { - m_rank_animation_duration[id] = 0.0f; + m_animation_duration[id] = 0.0f; m_animation_states[id] = AS_SMALLER; } } else { - m_rank_animation_duration[id] += dt; + m_animation_duration[id] += dt; } float scale = 1.0f; - int rank = kart->getPosition(); + int shown_number = number; const float DURATION = 0.4f; const float MIN_SHRINK = 0.3f; if (m_animation_states[id] == AS_SMALLER) { - scale = 1.0f - m_rank_animation_duration[id]/ DURATION; - rank = m_last_ranks[id]; + scale = 1.0f - m_animation_duration[id]/ DURATION; + shown_number = m_last_digit[id]; if (scale < MIN_SHRINK) { m_animation_states[id] = AS_BIGGER; - m_rank_animation_duration[id] = 0.0f; + m_animation_duration[id] = 0.0f; // Store the new rank - m_last_ranks[id] = kart->getPosition(); + m_last_digit[id] = number; scale = MIN_SHRINK; } } else if (m_animation_states[id] == AS_BIGGER) { - scale = m_rank_animation_duration[id] / DURATION + MIN_SHRINK; - rank = m_last_ranks[id]; + scale = m_animation_duration[id] / DURATION + MIN_SHRINK; + shown_number = m_last_digit[id]; if (scale > 1.0f) { m_animation_states[id] = AS_NONE; @@ -960,7 +966,7 @@ void RaceGUI::drawRank(const AbstractKart *kart, } else { - m_last_ranks[id] = kart->getPosition(); + m_last_digit[id] = number; } gui::ScalableFont* font = GUIEngine::getHighresDigitFont(); @@ -968,7 +974,7 @@ void RaceGUI::drawRank(const AbstractKart *kart, int font_height = font->getDimension(L"X").Height; font->setScale((float)meter_height / font_height * 0.4f * scale); std::ostringstream oss; - oss << rank; // the current font has no . :( << "."; + oss << shown_number; // the current font has no . :( << "."; core::recti pos; pos.LowerRightCorner = core::vector2di(int(offset.X + 0.64f*meter_width), diff --git a/src/states_screens/race_gui.hpp b/src/states_screens/race_gui.hpp index 0442ed9cf5b..bd966e1aac6 100644 --- a/src/states_screens/race_gui.hpp +++ b/src/states_screens/race_gui.hpp @@ -20,6 +20,7 @@ #ifndef HEADER_RACE_GUI_HPP #define HEADER_RACE_GUI_HPP +#include #include #include @@ -107,13 +108,13 @@ class RaceGUI : public RaceGUIBase /** Animation state: none, getting smaller (old value), * getting bigger (new number). */ enum AnimationState {AS_NONE, AS_SMALLER, AS_BIGGER}; - std::vector m_animation_states; + std::map m_animation_states; - /** How long the rank animation has been shown. */ - std::vector m_rank_animation_duration; + /** How long the speedometer digit animation has been shown for this number. */ + std::map m_animation_duration; - /** Stores the previous rank for each kart. Used for the rank animation. */ - std::vector m_last_ranks; + /** Stores the previous digit on the center of the speedometer for each number. */ + std::map m_last_digit; bool m_is_tutorial; diff --git a/src/tracks/track.cpp b/src/tracks/track.cpp index 67ccf059a79..738037c2124 100644 --- a/src/tracks/track.cpp +++ b/src/tracks/track.cpp @@ -657,10 +657,6 @@ void Track::loadTrackInfo() // Currently only max eight players in soccer mode m_max_arena_players = 8; } - // Max 10 players supported in arena - if (m_max_arena_players > 10) - m_max_arena_players = 10; - } // loadTrackInfo //-----------------------------------------------------------------------------