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:
@@ -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++)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
/** \} */
|
||||
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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];
|
||||
|
||||
|
||||
@@ -64,6 +64,14 @@ CheckManager::~CheckManager()
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/** Reverse checks order. */
|
||||
void CheckManager::reverse()
|
||||
{
|
||||
// FIXME
|
||||
} // reverse
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/** Resets all checks. */
|
||||
void CheckManager::reset(const Track &track)
|
||||
{
|
||||
|
||||
@@ -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(); }
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
{
|
||||
|
||||
@@ -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); }
|
||||
|
||||
Reference in New Issue
Block a user