1) Started adding new race result screen, which is for now disabled in the game.

2) Replaced int* with std::vector<int> in raceResultOrder.


git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@5682 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk 2010-07-15 22:41:41 +00:00
parent a00f81738f
commit 04f2bd7190
16 changed files with 359 additions and 29 deletions

View File

@ -317,6 +317,8 @@ supertuxkart_SOURCES = \
states_screens/race_gui_base.hpp \
states_screens/race_gui.cpp \
states_screens/race_gui.hpp \
states_screens/race_result_gui.cpp \
states_screens/race_result_gui.hpp \
states_screens/race_setup_screen.cpp \
states_screens/race_setup_screen.hpp \
states_screens/state_manager.cpp \

View File

@ -920,7 +920,7 @@
</File>
</Filter>
<Filter
Name="states_screen"
Name="states_screens"
>
<File
RelativePath="..\..\states_screens\addons_screen.cpp"
@ -998,6 +998,10 @@
RelativePath="..\..\states_screens\race_gui.cpp"
>
</File>
<File
RelativePath="..\..\states_screens\race_result_gui.cpp"
>
</File>
<File
RelativePath="..\..\states_screens\race_setup_screen.cpp"
>
@ -1848,6 +1852,10 @@
RelativePath="..\..\states_screens\race_gui_base.hpp"
>
</File>
<File
RelativePath="..\..\states_screens\race_result_gui.hpp"
>
</File>
<File
RelativePath="..\..\states_screens\race_setup_screen.hpp"
>

View File

@ -42,6 +42,7 @@
#include "modes/linear_world.hpp"
#include "network/network_manager.hpp"
#include "race/race_manager.hpp"
#include "states_screens/race_result_gui.hpp"
#include "tracks/quad_graph.hpp"
#include "tracks/track.hpp"
#include "utils/constants.hpp"
@ -124,6 +125,17 @@ void EndController::reset()
}
} // reset
//-----------------------------------------------------------------------------
/** The end controller must forward 'fire' presses to the race gui.
*/
void EndController::action(PlayerAction action, int value)
{
if(action!=PA_FIRE) return;
RaceResultGUI *race_result_gui = dynamic_cast<RaceResultGUI*>(World::getWorld()->getRaceGUI());
if(!race_result_gui) return;
race_result_gui->nextPhase();
} // action
//-----------------------------------------------------------------------------
void EndController::update(float dt)
{

View File

@ -101,6 +101,7 @@ public:
* controller. This way e.g. highscores can still be assigned
* to the right player. */
virtual bool isPlayerController () const {return m_player!=NULL;}
virtual void action (PlayerAction action, int value);
}; // EndKart

View File

@ -478,14 +478,15 @@ RaceGUIBase::KartIconDisplayInfo* LinearWorld::getKartsDisplayInfo()
// ----------------------------------------------------------------------------
/** Sets up the mapping from kart position to kart index.
*/
void LinearWorld::raceResultOrder( int order[] )
void LinearWorld::raceResultOrder(std::vector<int> *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;
(*order)[i] = -1;
}
bool positions_ok = true;
@ -497,18 +498,18 @@ void LinearWorld::raceResultOrder( int order[] )
#ifndef NDEBUG
// sanity checks
if (order[position] != -1)
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)
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 " << (*order)[j] << " is at position " << j << std::endl;
}
}
std::cout << "Kart " << i << " is being given posiiton " << (getKart(i)->getPosition()-1)
@ -518,7 +519,7 @@ void LinearWorld::raceResultOrder( int order[] )
#endif
// actually assign the position
order[position] = i; // even for eliminated karts
(*order)[position] = i; // even for eliminated karts
}
#ifndef NDEBUG

View File

@ -108,7 +108,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 raceResultOrder(std::vector<int> *order);
/** Returns true if the kart is on a valid driveline quad.
* \param kart_index Index of the kart.
*/

View File

@ -321,16 +321,19 @@ void ThreeStrikesBattle::moveKartAfterRescue(Kart* kart)
} // moveKartAfterRescue
//-----------------------------------------------------------------------------
void ThreeStrikesBattle::raceResultOrder( int* order )
void ThreeStrikesBattle::raceResultOrder(std::vector<int> *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;
(*order)[pos] = kart_id;
}
} // raceResultOrder

View File

@ -77,7 +77,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 raceResultOrder(std::vector<int> *order);
void updateKartRanks();
}; // ThreeStrikesBattles

View File

@ -26,14 +26,11 @@
#include <ctime>
#include "audio/music_manager.hpp"
#include "audio/sfx_manager.hpp"
#include "audio/sfx_base.hpp"
#include "audio/sfx_manager.hpp"
#include "challenges/unlock_manager.hpp"
#include "config/user_config.hpp"
#include "graphics/camera.hpp"
#include "states_screens/state_manager.hpp"
#include "states_screens/race_gui_base.hpp"
#include "states_screens/race_gui.hpp"
#include "io/file_manager.hpp"
#include "items/projectile_manager.hpp"
#include "karts/controller/default_ai_controller.hpp"
@ -47,6 +44,10 @@
#include "race/highscore_manager.hpp"
#include "race/history.hpp"
#include "race/race_manager.hpp"
#include "states_screens/state_manager.hpp"
#include "states_screens/race_gui_base.hpp"
#include "states_screens/race_gui.hpp"
#include "states_screens/race_result_gui.hpp"
#include "tracks/track.hpp"
#include "tracks/track_manager.hpp"
#include "utils/constants.hpp"
@ -294,8 +295,9 @@ void World::terminateRace()
updateHighscores();
unlock_manager->raceFinished();
RaceGUIBase* m = World::getWorld()->getRaceGUI();
if (m) m->clearAllMessages();
if (m_race_gui) m_race_gui->clearAllMessages();
delete m_race_gui;
m_race_gui = new RaceResultGUI();
WorldStatus::terminateRace();
} // terminateRace

View File

@ -252,7 +252,7 @@ public:
* the first kart, order[1] the ID of the second kart, etc...
* Array dimension must be the number of karts.
*/
virtual void raceResultOrder( int order[] ) = 0;
virtual void raceResultOrder(std::vector<int> *order ) = 0;
/** Returns the number of started karts, used to determine which karts
* receive a speed boost. */

View File

@ -179,7 +179,6 @@ void WorldStatus::update(const float dt)
{
m_phase = RESULT_DISPLAY_PHASE;
terminateRace();
new RaceOverDialog(0.6f, 0.9f);
}
break;
}

View File

@ -106,9 +106,8 @@ RaceOverDialog::RaceOverDialog(const float percentWidth,
World *world = World::getWorld();
const unsigned int num_karts = world->getNumKarts();
int* order = new int [num_karts];
for (unsigned int n=0; n<num_karts; n++) order[n] = -1;
world->raceResultOrder(order);
std::vector<int> order;
world->raceResultOrder(&order);
const bool display_time = (world->getClockMode() == WorldStatus::CLOCK_CHRONO);
@ -207,8 +206,6 @@ RaceOverDialog::RaceOverDialog(const float percentWidth,
kart_id++;
}
delete[] order;
// ---- Highscores
if (show_highscores)

View File

@ -20,13 +20,16 @@
#ifndef HEADER_RACE_GUI_BASE_HPP
#define HEADER_RACE_GUI_BASE_HPP
#include "irrlicht.h"
using namespace irr;
class Kart;
/**
* \brief An abstract base class for the two race guis (race_gui and
* race_result gui)
* \ingroup states_screens
*/
class Kart;
class RaceGUIBase
{
public:
@ -37,7 +40,7 @@ public:
struct KartIconDisplayInfo
{
/** text to display next to icon, if any */
irr::core::stringw m_text;
core::stringw m_text;
/** text color, if any text */
float r, g, b;

View File

@ -0,0 +1,201 @@
// $Id: race_result_gui.cpp 5424 2010-05-10 23:53:32Z hikerstk $
//
// 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 "states_screens/race_result_gui.hpp"
#include "guiengine/engine.hpp"
#include "modes/world.hpp"
#include "states_screens/dialogs/race_over_dialog.hpp"
#include "utils/string_utils.hpp"
/** Constructor, initialises internal data structures.
*/
RaceResultGUI::RaceResultGUI()
{
// FIXME: for now disable the new race result display
// by just firing up the old display (which will make sure
// that the rendering for this object is not called anymore).
new RaceOverDialog(0.6f, 0.9f);
return;
determineLayout();
m_timer = 0;
} // RaceResultGUI
//-----------------------------------------------------------------------------
/** Destructor. */
RaceResultGUI::~RaceResultGUI()
{
} // ~Racegui
//-----------------------------------------------------------------------------
/** This function is called when one of the player presses 'fire'. The next
* phase of the animation will be displayed. E.g.
* in a GP: pressing fire while/after showing the latest race result will
* start the animation for the current GP result
* in a normal race: when pressing fire while an animation is played,
* start the menu showing 'rerun, new race, back to main' etc.
*/
void RaceResultGUI::nextPhase()
{
new RaceOverDialog(0.6f, 0.9f);
} // nextPhase
//-----------------------------------------------------------------------------
/** This determines the layout, i.e. the size of all columns, font size etc.
*/
void RaceResultGUI::determineLayout()
{
// Top pixel where to display text
unsigned int top = (int)(0.15f*UserConfigParams::m_height);
// Height of the result display
unsigned int height = (int)(0.7f *UserConfigParams::m_height);
// How much time between consecutive rows
m_time_between_rows = 0.5f;
World *world = World::getWorld();
unsigned int num_karts = world->getNumKarts();
// Determine text height
m_font = GUIEngine::getFont();
core::dimension2du text_size = m_font->getDimension(L"a");
m_distance_between_rows = (int)(1.5f*text_size.Height);
// If there are too many karts, reduce size between rows
if(m_distance_between_rows * num_karts > height)
m_distance_between_rows = height / num_karts;
world->raceResultOrder(&m_order);
m_start_at.clear();
for(unsigned int i=0; i<num_karts; i++)
{
if(m_order[i]==-1) continue;
m_start_at.push_back(m_time_between_rows * i);
m_x_pos.push_back((float)UserConfigParams::m_width);
m_y_pos.push_back(m_distance_between_rows+i*m_distance_between_rows);
Kart *kart = world->getKart(m_order[i]);
const core::stringw& kart_name = kart->getName();
const float time = kart->getFinishTime();
std::string time_string = StringUtils::timeToString(time);
core::stringw kart_results_line = StringUtils::insertValues( L"%i. %s %s",
kart->getPosition(),
kart_name.c_str(),
time_string.c_str());
m_entry.push_back(core::stringw(kart_results_line.c_str()));
}
m_icon_width = UserConfigParams::m_height<600
? 27
: (int)(40*(UserConfigParams::m_width/800.0f));
// Determine the maximum width for the kart name column
unsigned int max_name_width = 0;
float max_finish_time = 0;
for(unsigned int i=0; i<num_karts; i++)
{
const Kart *kart = world->getKart(i);
core::dimension2d<u32> rect = m_font->getDimension(kart->getName().c_str());
if(rect.Width > max_name_width) max_name_width = rect.Width;
if(kart->getFinishTime() > max_finish_time)
max_finish_time = kart->getFinishTime();
} // for i<num_karts
// Not all digits have the same width. So to properly align the times
// and points, we have to do the layout one digit at a time, and we
// need the maximum size of one digit for that:
m_max_digit_width = 0;
for(char c='0'; c<='9'; c++)
{
wchar_t s[2];
s[0] = c; s[1]=0;
core::dimension2du r = m_font->getDimension(s);
if(r.Width > m_max_digit_width) m_max_digit_width = r.Width;
}
m_column_space_size = 20;
} // determineLayout
//-----------------------------------------------------------------------------
/** Render all global parts of the race gui, i.e. things that are only
* displayed once even in splitscreen.
* \param dt Timestep sized.
*/
void RaceResultGUI::renderGlobal(float dt)
{
World *world = World::getWorld();
assert(world->getPhase()==WorldStatus::RESULT_DISPLAY_PHASE);
m_timer += dt;
unsigned int num_karts = world->getNumKarts();
// How long it takes for one line to scroll from right to left
float scroll_duration = 0.5f;
float v = 0.9f*UserConfigParams::m_width/scroll_duration;
for(unsigned int i=0; i<num_karts; i++)
{
if(m_order[i]==-1) continue;
if(m_start_at[i]>m_timer) continue;
m_x_pos[i] -= dt*v;
if(m_x_pos[i]<0.1f*UserConfigParams::m_width)
m_x_pos[i] = 0.1f*UserConfigParams::m_width;
printf("%d: %f %d\n", i, m_x_pos[i], m_y_pos[i]);
displayOneEntry((unsigned int)(m_x_pos[i]), m_y_pos[i],
m_order[i], true);
}
} // renderGlobal
//-----------------------------------------------------------------------------
/** Displays the race results for a single kart.
* \param n Index of the kart to be displayed.
* \param display_points True if GP points should be displayed, too
*/
void RaceResultGUI::displayOneEntry(unsigned int x, unsigned int y,
unsigned int n, bool display_points)
{
World *world = World::getWorld();
video::SColor color;
// Display player karts in red
Kart *kart = world->getKart(n);
if(kart->getController()->isPlayerController())
color = video::SColor(255, 255, 0, 0);
else
color = video::SColor(255, 255, 255, 255);
// First draw the icon
// -------------------
video::ITexture *t = kart->getKartProperties()->getIconMaterial()->getTexture();
core::recti source_rect(core::vector2di(0,0), t->getSize());
core::recti dest_rect(x, y, x+m_icon_width, y+m_icon_width);
irr_driver->getVideoDriver()->draw2DImage(t, dest_rect, source_rect,
NULL, NULL, true);
// Draw the name
// -------------
core::recti pos(x+m_icon_width+m_column_space_size, y,
UserConfigParams::m_width, y+m_distance_between_rows);
m_font->draw(m_entry[n], pos, color);
} // displayOneEntry

View File

@ -0,0 +1,100 @@
// $Id: race_result_gui.hpp 5310 2010-04-28 18:26:23Z auria $
//
// 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_RACE_RESULT_GUI_HPP
#define HEADER_RACE_RESULT_GUI_HPP
#include <assert.h>
#include <vector>
#include "states_screens/race_gui_base.hpp"
/**
* \brief Displays the results (while the end animation is shown).
* \ingroup states_screens
*/
class RaceResultGUI : public RaceGUIBase
{
private:
float m_timer;
std::vector<float> m_start_at;
std::vector<float> m_x_pos;
std::vector<int> m_y_pos;
std::vector<core::stringw> m_entry;
/** Time to wait till the next row starts to be animated. */
float m_time_between_rows;
/** Distance between each row of the race results */
unsigned int m_distance_between_rows;
/** The size of the kart icons. */
unsigned int m_icon_width;
/** The width of the time column. */
unsigned int m_time_width;
/** The width of the point column. */
unsigned int m_column_width;
/** The order in which to display the karts. */
std::vector<int> m_order;
/** The width of the largest digit (not all digits
* have the same font size) */
unsigned int m_max_digit_width ;
/** Size of space between columns. */
unsigned int m_column_space_size;
/** The font to use. */
gui::IGUIFont* m_font;
void displayOneEntry(unsigned int x, unsigned int y,
unsigned int n, bool display_points);
void determineLayout();
public:
RaceResultGUI();
virtual ~RaceResultGUI();
virtual void renderGlobal(float dt);
/** Should not be called anymore. */
const core::dimension2du getMiniMapSize() const
{ assert(false); return core::dimension2du(0, 0); }
/** No kart specific view needs to be rendered in the result gui. */
virtual void renderPlayerView(const Kart *kart) {}
/** No more messages need to be displayed, so this function shouldn't
* be called at all. */
virtual void addMessage(const irr::core::stringw &m, const Kart *kart,
float time, int fonst_size,
const video::SColor &color=
video::SColor(255, 255, 0, 255),
bool important=true) { assert(false); }
/** Should not be called anymore. */
virtual void clearAllMessages() {assert(false); }
void nextPhase();
}; // RaceResultGUI
#endif

View File

@ -164,7 +164,8 @@ void StateManager::escapePressed()
// In-game
else if(m_game_mode == GAME)
{
new RacePausedDialog(0.8f, 0.6f);
if(World::getWorld()->getPhase()!=WorldStatus::RESULT_DISPLAY_PHASE)
RacePausedDialog(0.8f, 0.6f);
//resetAndGoToMenu("main.stkgui");
//input_manager->setMode(InputManager::MENU);
}