Improved new race result gui - it now consists of two parts: first

the results of the just finished race, then an animated display
of the GP standings (to test this please change the #undef
USE_NEW_RACE_RESULT in race_result_gui.cpp).


git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@5710 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk 2010-07-29 23:03:20 +00:00
parent 57b5c788ea
commit 0b35249b43
4 changed files with 165 additions and 85 deletions

View File

@ -99,7 +99,18 @@ void RaceManager::setLocalKartInfo(unsigned int player_id, const std::string& ka
} // setLocalKartInfo } // setLocalKartInfo
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** Returns the kart with a given GP rank (or NULL if no such kart exists).
* \param n Rank (0<=n<num_karts) to look for.
*/
const Kart *RaceManager::getKartWithGPRank(unsigned int n)
{
for(unsigned int i=0; i<m_kart_status.size(); i++)
if(m_kart_status[i].m_gp_rank == n)
return World::getWorld()->getKart(i);
return NULL;
} // getKLartWithGPRank
//-----------------------------------------------------------------------------
int RaceManager::getLocalPlayerGPRank(const int playerID) const int RaceManager::getLocalPlayerGPRank(const int playerID) const
{ {
const int amount = m_kart_status.size(); const int amount = m_kart_status.size();
@ -199,8 +210,13 @@ void RaceManager::startNew()
// First add the AI karts (randomly chosen) // First add the AI karts (randomly chosen)
// ---------------------------------------- // ----------------------------------------
int init_gp_rank = 0;
for(unsigned int i=0; i<m_random_kart_list.size(); i++) for(unsigned int i=0; i<m_random_kart_list.size(); i++)
m_kart_status.push_back(KartStatus(m_random_kart_list[i], i, -1, -1, KT_AI)); {
m_kart_status.push_back(KartStatus(m_random_kart_list[i], i, -1, -1,
init_gp_rank, KT_AI));
init_gp_rank ++;
}
// Then the players, which start behind the AI karts // Then the players, which start behind the AI karts
// ------------------------------------------------- // -------------------------------------------------
@ -211,8 +227,9 @@ void RaceManager::startNew()
m_kart_status.push_back(KartStatus(m_player_karts[i].getKartName(), i, m_kart_status.push_back(KartStatus(m_player_karts[i].getKartName(), i,
m_player_karts[i].getLocalPlayerId(), m_player_karts[i].getLocalPlayerId(),
m_player_karts[i].getGlobalPlayerId(), m_player_karts[i].getGlobalPlayerId(),
kt init_gp_rank, kt
) ); ) );
init_gp_rank ++;
} }
// Then start the race with the first track // Then start the race with the first track
@ -322,12 +339,11 @@ void RaceManager::computeGPRanks()
{ {
// calculate the rank of each kart // calculate the rank of each kart
const unsigned int NUM_KARTS = getNumberOfKarts(); const unsigned int NUM_KARTS = getNumberOfKarts();
int *scores = new int[NUM_KARTS];
int *scores = new int[NUM_KARTS]; int *position = new int[NUM_KARTS];
int *position = new int[NUM_KARTS]; double *race_time = new double[NUM_KARTS];
double *race_time = new double[NUM_KARTS];
// Ignore the first kart if it's a follow-the-leader race. // Ignore the first kart if it's a follow-the-leader race.
int start=(race_manager->getMinorMode()==RaceManager::MINOR_MODE_FOLLOW_LEADER) ? 1 : 0; int start=(race_manager->getMinorMode()==RaceManager::MINOR_MODE_FOLLOW_LEADER);
for (unsigned int kart_id = start; kart_id < NUM_KARTS; ++kart_id) for (unsigned int kart_id = start; kart_id < NUM_KARTS; ++kart_id)
{ {
position[kart_id] = kart_id; position[kart_id] = kart_id;
@ -394,7 +410,6 @@ void RaceManager::exitRace()
// were finished, and not when a race is aborted. // were finished, and not when a race is aborted.
if (m_major_mode==MAJOR_MODE_GRAND_PRIX && m_track_number==(int)m_tracks.size()) if (m_major_mode==MAJOR_MODE_GRAND_PRIX && m_track_number==(int)m_tracks.size())
{ {
computeGPRanks();
unlock_manager->grandPrixFinished(); unlock_manager->grandPrixFinished();
StateManager::get()->resetAndGoToScreen( MainMenuScreen::getInstance() ); StateManager::get()->resetAndGoToScreen( MainMenuScreen::getInstance() );

View File

@ -188,20 +188,23 @@ private:
std::string m_player_name; // for networked karts std::string m_player_name; // for networked karts
int m_score; // score for this kart int m_score; // score for this kart
int m_last_score; // needed for restart race, and for race results GUI. int m_last_score; // needed for restart race, and for race results GUI.
double m_overall_time; // sum of times of all races float m_overall_time; // sum of times of all races
double m_last_time; // needed for restart float m_last_time; // needed for restart
int m_prev_finish_pos; // previous finished position int m_prev_finish_pos; // previous finished position
KartType m_kart_type; // Kart type: AI, player, network player etc. KartType m_kart_type; // Kart type: AI, player, network player etc.
int m_local_player_id; // player controling the kart, for AI: -1 int m_local_player_id; // player controling the kart, for AI: -1
int m_global_player_id; // global ID of player int m_global_player_id; // global ID of player
int m_gp_rank; // In GPs, at the end, will hold the overall rank of this kart. int m_gp_rank; // In GPs, at the end, will hold the overall
// rank of this kart (0<=m_gp_rank < num_karts-1)
KartStatus(const std::string& ident, const int& prev_finish_pos, KartStatus(const std::string& ident, const int& prev_finish_pos,
int local_player_id, int global_player_id, KartType kt) : int local_player_id, int global_player_id,
int init_gp_rank, KartType kt) :
m_ident(ident), m_score(0), m_last_score(0), m_ident(ident), m_score(0), m_last_score(0),
m_overall_time(0.0f), m_last_time(0.0f), m_overall_time(0.0f), m_last_time(0.0f),
m_prev_finish_pos(prev_finish_pos), m_kart_type(kt), m_prev_finish_pos(prev_finish_pos), m_kart_type(kt),
m_local_player_id(local_player_id), m_local_player_id(local_player_id),
m_gp_rank(init_gp_rank),
m_global_player_id(global_player_id) m_global_player_id(global_player_id)
{} {}
@ -283,7 +286,7 @@ public:
void computeGPRanks(); void computeGPRanks();
int getKartGPRank(const int kart_id) int getKartGPRank(const int kart_id)
const { return m_kart_status[kart_id].m_gp_rank; } const { return m_kart_status[kart_id].m_gp_rank; }
const Kart* getKartWithGPRank(unsigned int n);
/** \return the GP rank of a local player, or -1 if the given player ID doesn't exist */ /** \return the GP rank of a local player, or -1 if the given player ID doesn't exist */
int getLocalPlayerGPRank(const int playerID) const; int getLocalPlayerGPRank(const int playerID) const;
@ -295,7 +298,7 @@ public:
const { return m_kart_status[k].m_local_player_id; } const { return m_kart_status[k].m_local_player_id; }
int getKartGlobalPlayerId(int k) int getKartGlobalPlayerId(int k)
const { return m_kart_status[k].m_global_player_id; } const { return m_kart_status[k].m_global_player_id; }
double getOverallTime(int kart) const { return m_kart_status[kart].m_overall_time;} float getOverallTime(int kart) const { return m_kart_status[kart].m_overall_time;}
KartType getKartType(int kart) const { return m_kart_status[kart].m_kart_type;} KartType getKartType(int kart) const { return m_kart_status[kart].m_kart_type;}
int getCoinTarget() const { return m_coin_target; } int getCoinTarget() const { return m_coin_target; }
int getPositionScore(int p) const { return m_score_for_position[p-1]; } int getPositionScore(int p) const { return m_score_for_position[p-1]; }

View File

@ -29,7 +29,7 @@
*/ */
RaceResultGUI::RaceResultGUI() RaceResultGUI::RaceResultGUI()
{ {
#define USE_NEW_RACE_RESULT #undef USE_NEW_RACE_RESULT
#ifndef USE_NEW_RACE_RESULT #ifndef USE_NEW_RACE_RESULT
// FIXME: for now disable the new race result display // FIXME: for now disable the new race result display
@ -38,9 +38,9 @@ RaceResultGUI::RaceResultGUI()
new RaceOverDialog(0.6f, 0.9f); new RaceOverDialog(0.6f, 0.9f);
return; return;
#else #else
determineLayout(); determineTableLayout();
m_timer = 0; m_timer = 0;
m_animation_state = RR_BEGIN_FIRST_TABLE; m_animation_state = RR_INIT;
#endif #endif
} // RaceResultGUI } // RaceResultGUI
@ -63,20 +63,21 @@ RaceResultGUI::~RaceResultGUI()
*/ */
void RaceResultGUI::nextPhase() void RaceResultGUI::nextPhase()
{ {
// FIXME: make sure that computeGPRanks is called here!!
new RaceOverDialog(0.6f, 0.9f); new RaceOverDialog(0.6f, 0.9f);
} // nextPhase } // nextPhase
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** This determines the layout, i.e. the size of all columns, font size etc. /** This determines the layout, i.e. the size of all columns, font size etc.
*/ */
void RaceResultGUI::determineLayout() void RaceResultGUI::determineTableLayout()
{ {
m_font = GUIEngine::getFont(); m_font = GUIEngine::getFont();
assert(m_font);
m_was_monospace = m_font->getMonospaceDigits(); m_was_monospace = m_font->getMonospaceDigits();
m_font->setMonospaceDigits(true); m_font->setMonospaceDigits(true);
assert(m_font);
World *world = World::getWorld(); World *world = World::getWorld();
std::vector<int> order; std::vector<int> order;
world->raceResultOrder(&order); world->raceResultOrder(&order);
@ -103,10 +104,6 @@ void RaceResultGUI::determineLayout()
core::dimension2d<u32> rect = m_font->getDimension(kart->getName().c_str()); core::dimension2d<u32> rect = m_font->getDimension(kart->getName().c_str());
if(rect.Width > m_width_kart_name) if(rect.Width > m_width_kart_name)
m_width_kart_name = rect.Width; m_width_kart_name = rect.Width;
m_new_points.push_back(race_manager->getPositionScore(i+1));
int p = race_manager->getKartPrevScore(order[i]);
m_new_overall_points.push_back(p+m_new_points[i]);
m_current_displayed_points.push_back((float)p);
} // for i < order.size() } // for i < order.size()
std::string max_time = StringUtils::timeToString(max_finish_time); std::string max_time = StringUtils::timeToString(max_finish_time);
@ -119,7 +116,7 @@ void RaceResultGUI::determineLayout()
unsigned int num_karts = m_finish_time_string.size(); unsigned int num_karts = m_finish_time_string.size();
// Top pixel where to display text // Top pixel where to display text
unsigned int top = (int)(0.15f*UserConfigParams::m_height); m_top = (int)(0.15f*UserConfigParams::m_height);
// Height of the result display // Height of the result display
unsigned int height = (int)(0.7f *UserConfigParams::m_height); unsigned int height = (int)(0.7f *UserConfigParams::m_height);
@ -133,7 +130,7 @@ void RaceResultGUI::determineLayout()
m_time_single_scroll = 0.2f; m_time_single_scroll = 0.2f;
// Time to rotate the entries to the proper GP position. // Time to rotate the entries to the proper GP position.
m_time_rotation = 2.0f; m_time_rotation = 1.0f;
// The time the first phase is being displayed: add the start time // The time the first phase is being displayed: add the start time
// of the last kart to the duration of the scroll plus some time // of the last kart to the duration of the scroll plus some time
@ -162,10 +159,10 @@ void RaceResultGUI::determineLayout()
// Determine width of new points column // Determine width of new points column
core::dimension2du r_new_p = m_font->getDimension(L"+99"); core::dimension2du r_new_p = m_font->getDimension(L"+99");
m_width_new_points = r_new_p.Width; m_width_new_points = r_new_p.Width;
// Determine width of overall points column // Determine width of overall points column
core::dimension2du r_all_p = m_font->getDimension(L"9999"); core::dimension2du r_all_p = m_font->getDimension(L"9999");
unsigned int width_all_points = r_all_p.Width; unsigned int width_all_points = r_all_p.Width;
unsigned int table_width = m_width_icon + m_width_kart_name unsigned int table_width = m_width_icon + m_width_kart_name
@ -177,27 +174,7 @@ void RaceResultGUI::determineLayout()
+ 2 * m_width_column_space; + 2 * m_width_column_space;
m_leftmost_column = (UserConfigParams::m_width - table_width)/2; m_leftmost_column = (UserConfigParams::m_width - table_width)/2;
if(race_manager->getMajorMode()==RaceManager::MAJOR_MODE_GRAND_PRIX) } // determineTableLayout
race_manager->computeGPRanks();
m_start_at.clear();
for(unsigned int i=0; i<num_karts; i++)
{
m_start_at.push_back(m_time_between_rows * i);
m_x_pos.push_back((float)UserConfigParams::m_width);
m_y_pos.push_back(top+i*m_distance_between_rows);
if(race_manager->getMajorMode()==RaceManager::MAJOR_MODE_GRAND_PRIX)
{
int gp_position = race_manager->getKartGPRank(order[i]);
if(gp_position<(int)i)
printf("X");
m_radius.push_back( (gp_position-(int)i)*(int)m_distance_between_rows*0.5f);
m_centre_point.push_back(top+(gp_position+i)*m_distance_between_rows*0.5f);
}
} // i < num_karts
} // determineLayout
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** Render all global parts of the race gui, i.e. things that are only /** Render all global parts of the race gui, i.e. things that are only
@ -210,31 +187,57 @@ void RaceResultGUI::renderGlobal(float dt)
World *world = World::getWorld(); World *world = World::getWorld();
assert(world->getPhase()==WorldStatus::RESULT_DISPLAY_PHASE); assert(world->getPhase()==WorldStatus::RESULT_DISPLAY_PHASE);
unsigned int num_karts = world->getNumKarts(); unsigned int num_karts = world->getNumKarts();
// First: Update the finite state machine, and set
// the current X and Y positions.
// ===============================================
switch(m_animation_state) switch(m_animation_state)
{ {
case RR_BEGIN_FIRST_TABLE: if(m_timer > m_time_overall_scroll) case RR_INIT:
{ for(unsigned int i=0; i<num_karts; i++)
m_animation_state = RR_INCREASE_POINTS; {
m_timer = 0; m_start_at.push_back(m_time_between_rows * i);
} m_x_pos.push_back((float)UserConfigParams::m_width);
break; m_y_pos.push_back((float)(m_top+i*m_distance_between_rows));
case RR_INCREASE_POINTS: if(m_timer > 5) }
{ m_animation_state = RR_RACE_RESULT;
m_animation_state = RR_RESORT_TABLE; break;
m_timer = 0; case RR_RACE_RESULT:
} if(m_timer > m_time_overall_scroll)
break; {
case RR_RESORT_TABLE: if(m_timer > m_time_rotation) if(race_manager->getMajorMode()!=RaceManager::MAJOR_MODE_GRAND_PRIX)
{ {
m_animation_state = RR_WAIT_TILL_END; m_animation_state = RR_WAIT_TILL_END;
// Make the new row permanent. break;
for(unsigned int i=0; i<num_karts; i++) }
m_y_pos[i] = m_centre_point[i]
+ m_radius[i]; determineGPLayout();
} m_animation_state = RR_OLD_GP_RESULTS;
break; m_timer = 0;
}
break;
case RR_OLD_GP_RESULTS:
if(m_timer > m_time_overall_scroll)
{
m_animation_state = RR_INCREASE_POINTS;
m_timer = 0;
}
case RR_INCREASE_POINTS:
if(m_timer > 5)
{
m_animation_state = RR_RESORT_TABLE;
m_timer = 0;
}
break;
case RR_RESORT_TABLE:
if(m_timer > m_time_rotation)
{
m_animation_state = RR_WAIT_TILL_END;
// Make the new row permanent.
for(unsigned int i=0; i<num_karts; i++)
m_y_pos[i] = m_centre_point[i] - m_radius[i];
}
break;
case RR_WAIT_TILL_END: break; case RR_WAIT_TILL_END: break;
} // switch } // switch
@ -245,7 +248,9 @@ void RaceResultGUI::renderGlobal(float dt)
float y = (float)m_y_pos[i]; float y = (float)m_y_pos[i];
switch(m_animation_state) switch(m_animation_state)
{ {
case RR_BEGIN_FIRST_TABLE: // Both states use the same scrolling:
case RR_RACE_RESULT:
case RR_OLD_GP_RESULTS:
if(m_timer > m_start_at[i]) if(m_timer > m_start_at[i])
{ // if active { // if active
m_x_pos[i] -= dt*v; m_x_pos[i] -= dt*v;
@ -272,6 +277,52 @@ void RaceResultGUI::renderGlobal(float dt)
} }
} // renderGlobal } // renderGlobal
//-----------------------------------------------------------------------------
/** Determine the layout and fields for the GP table based on the previous
* GP results.
*/
void RaceResultGUI::determineGPLayout()
{
unsigned int num_karts = m_kart_icons.size();
m_current_displayed_points.resize(num_karts);
m_new_points.resize(num_karts);
std::vector<int> old_rank(num_karts, 0);
for(unsigned int kart_id=0; kart_id<num_karts; kart_id++)
{
int rank = race_manager->getKartGPRank(kart_id);
old_rank[kart_id] = rank;
const Kart *kart = World::getWorld()->getKart(kart_id);
m_kart_icons[rank] =
kart->getKartProperties()->getIconMaterial()->getTexture();
m_kart_names[rank] = kart->getName();
float time = race_manager->getOverallTime(kart_id);
m_finish_time_string[rank]
= StringUtils::timeToString(time).c_str();
m_start_at[rank] = m_time_between_rows * rank;
m_x_pos[rank] = (float)UserConfigParams::m_width;
m_y_pos[rank] = (float)(m_top+rank*m_distance_between_rows);
int p = race_manager->getKartPrevScore(kart_id);
m_current_displayed_points[rank] = (float)p;
m_new_points[rank] = race_manager->getPositionScore(kart->getPosition());
}
// Now update the GP ranks, and determine the new position
// -------------------------------------------------------
m_radius.resize(num_karts);
m_centre_point.resize(num_karts);
m_new_overall_points.resize(num_karts);
race_manager->computeGPRanks();
for(unsigned int i=0; i<num_karts; i++)
{
int j = old_rank[i];
int gp_position = race_manager->getKartGPRank(i);
m_radius[j] = (j-gp_position)*(int)m_distance_between_rows*0.5f;
m_centre_point[j] = m_top+(gp_position+j)*m_distance_between_rows*0.5f;
int p = race_manager->getKartScore(i);
m_new_overall_points[j] = p;
} // i < num_karts
} // determineGPLayout
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** Displays the race results for a single kart. /** Displays the race results for a single kart.
* \param n Index of the kart to be displayed. * \param n Index of the kart to be displayed.
@ -312,9 +363,11 @@ void RaceResultGUI::displayOneEntry(unsigned int x, unsigned int y,
m_font->draw(m_finish_time_string[n], dest_rect, color); m_font->draw(m_finish_time_string[n], dest_rect, color);
m_font->setMonospaceDigits(mono); m_font->setMonospaceDigits(mono);
// Only display points in GP mode.
// =============================== // Only display points in GP mode and when the GP results are displayed.
if(race_manager->getMajorMode()!=RaceManager::MAJOR_MODE_GRAND_PRIX) // =====================================================================
if(race_manager->getMajorMode()!=RaceManager::MAJOR_MODE_GRAND_PRIX ||
m_animation_state == RR_RACE_RESULT)
return; return;
// Draw the new points // Draw the new points

View File

@ -44,13 +44,18 @@ private:
float m_timer; float m_timer;
/** Finite state machine for the animations: /** Finite state machine for the animations:
BEGIN_FIRST_TABLE: The rows scroll into place. INIT: Set up data structures.
INCREASE_POINTS: The overall points are added up RACE_RESULT: The rows scroll into place.
RESORT_TABLE: Resort the table so that it is now sorted by OLD_GP_TABLE: Scroll new table into place, sorted by previous
GP points. GP ranks
WAIT_TILL_END Some delay to wait for end, after a period it INCREASE_POINTS: The overall points are added up
wii automatically end. */ RESORT_TABLE: Resort the table so that it is now sorted by
enum {RR_BEGIN_FIRST_TABLE, GP points.
WAIT_TILL_END Some delay to wait for end, after a period it
wii automatically end. */
enum {RR_INIT,
RR_RACE_RESULT,
RR_OLD_GP_RESULTS,
RR_INCREASE_POINTS, RR_INCREASE_POINTS,
RR_RESORT_TABLE, RR_RESORT_TABLE,
RR_WAIT_TILL_END} RR_WAIT_TILL_END}
@ -63,7 +68,7 @@ private:
std::vector<float> m_x_pos; std::vector<float> m_x_pos;
/** Currenct Y position. */ /** Currenct Y position. */
std::vector<int> m_y_pos; std::vector<float> m_y_pos;
/** The center point when sorting the entries. */ /** The center point when sorting the entries. */
std::vector<float> m_centre_point; std::vector<float> m_centre_point;
@ -131,6 +136,9 @@ private:
table is aligned. */ table is aligned. */
unsigned int m_leftmost_column; unsigned int m_leftmost_column;
/** Top-most pixel for first row. */
unsigned int m_top;
/** Size of space between columns. */ /** Size of space between columns. */
unsigned int m_width_column_space; unsigned int m_width_column_space;
@ -142,7 +150,8 @@ private:
void displayOneEntry(unsigned int x, unsigned int y, void displayOneEntry(unsigned int x, unsigned int y,
unsigned int n, bool display_points); unsigned int n, bool display_points);
void determineLayout(); void determineTableLayout();
void determineGPLayout();
public: public: