Applied first part of MCMic's patch to allow driving a track in reverse.

It adds a flag to the track.xml files, a (currently unnamed) checkbox
in the track selection screen, but doesn't do any actualy reversing (see
forum http://forum.freegamedev.net/viewtopic.php?f=18&t=2661 for
details).


git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/reverse_mode@10767 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk
2012-01-30 23:35:46 +00:00
11 changed files with 96 additions and 20 deletions

View File

@@ -107,7 +107,7 @@ void World::init()
m_eliminated_karts = 0;
m_eliminated_players = 0;
m_num_players = 0;
// Create the race gui before anything else is attached to the scene node
// (which happens when the track is loaded). This allows the race gui to
// do any rendering on texture.
@@ -132,7 +132,7 @@ void World::init()
// Load the track models - this must be done before the karts so that the
// karts can be positioned properly on (and not in) the tracks.
m_track->loadTrackModel(this);
m_track->loadTrackModel(this, race_manager->getReverseTrack());
for(unsigned int i=0; i<num_karts; i++)
{

View File

@@ -351,7 +351,7 @@ void RaceManager::startNextRace()
else if(m_minor_mode==MINOR_MODE_FOLLOW_LEADER)
World::setWorld(new FollowTheLeaderRace());
else if(m_minor_mode==MINOR_MODE_NORMAL_RACE ||
m_minor_mode==MINOR_MODE_TIME_TRIAL)
m_minor_mode==MINOR_MODE_TIME_TRIAL)
World::setWorld(new StandardRace());
else if(m_minor_mode==MINOR_MODE_3_STRIKES)
World::setWorld(new ThreeStrikesBattle());
@@ -616,12 +616,14 @@ void RaceManager::startGP(const GrandPrixData* gp)
//-----------------------------------------------------------------------------
void RaceManager::startSingleRace(const std::string trackIdent, const int num_laps)
void RaceManager::startSingleRace(const std::string trackIdent,
const int num_laps, const bool reverse_track)
{
StateManager::get()->enterGameState();
setTrack(trackIdent.c_str());
if (num_laps != -1) setNumLaps( num_laps );
setReverseTrack(reverse_track);
setMajorMode(RaceManager::MAJOR_MODE_SINGLE);

View File

@@ -250,6 +250,9 @@ private:
/** The number of laps for each track of a GP (only one element
* is used if only a single track is used. */
std::vector<int> m_num_laps;
/** Whether a track should be reversed */
std::vector<bool> m_reverse_track;
/** The points given to a kart on a given position (index is
* 0 based, so using race-position - 1. */
@@ -315,6 +318,10 @@ public:
void setNumLaps(int num) { m_num_laps.clear();
m_num_laps.push_back(num); }
void setReverseTrack(bool r_t) { m_reverse_track.clear();
m_reverse_track.push_back(r_t); }
void setMajorMode(MajorRaceModeType mode)
{ m_major_mode = mode; }
void setMinorMode(MinorRaceModeType mode)
@@ -358,6 +365,9 @@ public:
return 9999;
return m_num_laps[m_track_number];
} // getNumLaps
// ------------------------------------------------------------------------
/** \return whether the track should be reversed */
bool getReverseTrack() const { return m_reverse_track[m_track_number]; }
Difficulty getDifficulty() const { return m_difficulty; }
const std::string& getTrackName() const { return m_tracks[m_track_number]; }
@@ -481,11 +491,15 @@ public:
void startGP(const GrandPrixData* gp);
/**
* \brief Higher-level method to start a GP without having to care about the exact startup sequence
* \brief Higher-level method to start a GP without having to care about
* the exact startup sequence.
* \param trackIdent Internal name of the track to race on
* \param num_laps Number of laps to race, or -1 if number of laps is not relevant in current mode
* \param num_laps Number of laps to race, or -1 if number of laps is
* not relevant in current mode
* \param reverse_track True if the track should be driven reverse
*/
void startSingleRace(const std::string trackIdent, const int num_laps);
void startSingleRace(const std::string trackIdent, const int num_laps,
const bool reverse_track);
/** \} */

View File

@@ -135,7 +135,7 @@ TrackInfoDialog::TrackInfoDialog(const std::string& ribbonItem, const std::strin
//I18N: In the track setup screen (number of laps choice, where %i is the number)
m_spinner->setText( _("%i laps") );
m_widgets.push_back(m_spinner);
//~ m_widgets.push_back(m_spinner);
m_spinner->add();
m_spinner->setValue( UserConfigParams::m_num_laps );
m_spinner->getIrrlichtElement()->setTabStop(true);
@@ -146,6 +146,30 @@ TrackInfoDialog::TrackInfoDialog(const std::string& ribbonItem, const std::strin
m_spinner = NULL;
}
// Reverse track
const bool reverse_available = track->reverseAvailable();
if (reverse_available)
{
m_checkbox = new CheckBoxWidget();
m_checkbox->m_x = m_area.getWidth()/2 - 400;
m_checkbox->m_y = (y2+y3)/2.0;
m_checkbox->m_w = 60;
m_checkbox->m_h = 60;
m_checkbox->setParent(m_irrlicht_window);
m_checkbox->m_properties[PROP_ID] = "reversecheckbox";
m_checkbox->m_properties[PROP_WARP_AROUND] = "true";
m_checkbox->setText( _("Reverse track") );
m_widgets.push_back(m_checkbox);
m_checkbox->add();
m_checkbox->setState(false);
m_checkbox->getIrrlichtElement()->setTabStop(true);
m_checkbox->getIrrlichtElement()->setTabGroup(false);
}
else
{
m_checkbox = NULL;
}
// ---- Start button
ButtonWidget* okBtn = new ButtonWidget();
okBtn->m_properties[PROP_ID] = "start";
@@ -290,7 +314,9 @@ void TrackInfoDialog::onEnterPressedInternal()
ModalDialog::dismiss();
const int num_laps = (m_spinner == NULL ? -1 : m_spinner->getValue());
race_manager->startSingleRace(m_track_ident, num_laps);
const bool reverse_track = m_checkbox == NULL ? false
: m_checkbox->getState();
race_manager->startSingleRace(m_track_ident, num_laps, reverse_track);
}
// ------------------------------------------------------------------------------------------------------
@@ -302,9 +328,11 @@ GUIEngine::EventPropagation TrackInfoDialog::processEvent(const std::string& eve
// Create a copy of member variables we still need, since they will
// not be accessible after dismiss:
const int num_laps = (m_spinner == NULL ? -1 : m_spinner->getValue());
const bool reverse_track = m_checkbox == NULL ? false
: m_checkbox->getState();
std::string track_ident = m_track_ident;
ModalDialog::dismiss();
race_manager->startSingleRace(track_ident, num_laps);
race_manager->startSingleRace(track_ident, num_laps, reverse_track);
return GUIEngine::EVENT_BLOCK;
}
else if (eventSource == "lapcountspinner")

View File

@@ -21,6 +21,7 @@
#include "guiengine/modaldialog.hpp"
#include "guiengine/widgets/spinner_widget.hpp"
#include "guiengine/widgets/check_box_widget.hpp"
static const int HIGHSCORE_COUNT = 3;
@@ -38,6 +39,7 @@ class TrackInfoDialog : public GUIEngine::ModalDialog
// When there is no need to tab through / click on images/labels, we can add directly
// irrlicht labels (more complicated uses require the use of our widget set)
GUIEngine::SpinnerWidget* m_spinner;
GUIEngine::CheckBoxWidget* m_checkbox;
irr::gui::IGUIImage* m_kart_icons[HIGHSCORE_COUNT];
irr::gui::IGUIStaticText* m_highscore_entries[HIGHSCORE_COUNT];

View File

@@ -64,6 +64,14 @@ CheckManager::~CheckManager()
// ----------------------------------------------------------------------------
/** Reverse checks order. */
void CheckManager::reverse()
{
// FIXME
} // reverse
// ----------------------------------------------------------------------------
/** Resets all checks. */
void CheckManager::reset(const Track &track)
{

View File

@@ -39,6 +39,7 @@ public:
~CheckManager();
void update(float dt);
void reset(const Track &track);
void reverse();
int getCheckStructureCount() const { return m_all_checks.size(); }

View File

@@ -43,7 +43,8 @@ QuadGraph *QuadGraph::m_quad_graph = NULL;
* \param graph_file_name Name of the file describing the actual graph
*/
QuadGraph::QuadGraph(const std::string &quad_file_name,
const std::string graph_file_name)
const std::string graph_file_name,
const bool reverse)
{
m_node = NULL;
m_mesh = NULL;

View File

@@ -85,7 +85,8 @@ private:
const video::SColor *track_color=NULL,
const video::SColor *lap_color=NULL);
QuadGraph (const std::string &quad_file_name,
const std::string graph_file_name);
const std::string graph_file_name,
const bool reverse);
~QuadGraph ();
public:
static const int UNKNOWN_SECTOR;
@@ -125,10 +126,11 @@ public:
// ----------------------------------------------------------------------
/** Creates a QuadGraph instance. */
static void create(const std::string &quad_file_name,
const std::string graph_file_name)
const std::string graph_file_name,
const bool reverse)
{
assert(m_quad_graph==NULL);
m_quad_graph = new QuadGraph(quad_file_name, graph_file_name);
m_quad_graph = new QuadGraph(quad_file_name, graph_file_name, reverse);
} // create
// ----------------------------------------------------------------------
/** Cleans up the quad graph. It is possible that this function is called

View File

@@ -86,6 +86,7 @@ Track::Track(const std::string &filename)
m_track_mesh = NULL;
m_gfx_effect_mesh = NULL;
m_internal = false;
m_reverse_available = false;
m_all_nodes.clear();
m_all_cached_meshes.clear();
m_is_arena = false;
@@ -298,6 +299,7 @@ void Track::loadTrackInfo()
root->get("arena", &m_is_arena);
root->get("groups", &m_groups);
root->get("internal", &m_internal);
root->get("reverse", &m_reverse_available);
for(unsigned int i=0; i<root->getNumNodes(); i++)
{
@@ -384,10 +386,11 @@ void Track::startMusic() const
/** Loads the quad graph, i.e. the definition of all quads, and the way
* they are connected to each other.
*/
void Track::loadQuadGraph(unsigned int mode_id)
void Track::loadQuadGraph(unsigned int mode_id, const bool reverse)
{
QuadGraph::create(m_root+"/"+m_all_modes[mode_id].m_quad_name,
m_root+"/"+m_all_modes[mode_id].m_graph_name);
m_root+"/"+m_all_modes[mode_id].m_graph_name,
reverse);
QuadGraph::get()->setupPaths();
#ifdef DEBUG
@@ -1141,8 +1144,13 @@ void Track::createWater(const XMLNode &node)
* scene, quad, and graph file to load.
*/
void Track::loadTrackModel(World* parent, unsigned int mode_id)
void Track::loadTrackModel(World* parent, bool reverse_track,
unsigned int mode_id )
{
if(!m_reverse_available)
{
reverse_track = false;
}
assert(m_all_cached_meshes.size()==0);
if(UserConfigParams::logMemory())
{
@@ -1206,7 +1214,7 @@ void Track::loadTrackModel(World* parent, unsigned int mode_id)
// the race gui was created. The race gui is needed since it stores
// the information about the size of the texture to render the mini
// map to.
if (!m_is_arena) loadQuadGraph(mode_id);
if (!m_is_arena) loadQuadGraph(mode_id, reverse_track);
// Set the default start positions. Node that later the default
// positions can still be overwritten.
@@ -1308,6 +1316,9 @@ void Track::loadTrackModel(World* parent, unsigned int mode_id)
else if(name=="checks")
{
m_check_manager = new CheckManager(*node, this);
if(reverse_track) {
m_check_manager->reverse();
}
}
else if (name=="particle-emitter")
{

View File

@@ -179,6 +179,9 @@ private:
* in the track seelction screen
*/
bool m_internal;
/** Whether this track should be available in reverse version */
bool m_reverse_available;
/** The type of sky to be used for the track. */
enum {SKY_NONE, SKY_BOX,
@@ -282,7 +285,7 @@ private:
void loadTrackInfo();
void itemCommand(const Vec3 &xyz, Item::ItemType item_type,
bool drop);
void loadQuadGraph(unsigned int mode_id);
void loadQuadGraph(unsigned int mode_id, const bool reverse);
void convertTrackToBullet(scene::ISceneNode *node);
bool loadMainTrack(const XMLNode &node);
void createWater(const XMLNode &node);
@@ -294,6 +297,8 @@ private:
public:
bool reverseAvailable() { return m_reverse_available; }
static const float NOHIT;
Track (const std::string &filename);
@@ -321,7 +326,9 @@ public:
// ------------------------------------------------------------------------
bool isArena () const { return m_is_arena; }
// ------------------------------------------------------------------------
void loadTrackModel (World* parent, unsigned int mode_id=0);
void loadTrackModel (World* parent,
bool reverse_track = false,
unsigned int mode_id=0);
// ------------------------------------------------------------------------
void addMusic (MusicInformation* mi)
{m_music.push_back(mi); }