More refactoring: duplicated code handling track sectors and

distance along track is now moved into a separate class TrackSector
and used in linear_world and rubber ball.


git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@9422 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk 2011-08-04 23:33:41 +00:00
parent 428ed5a07b
commit 6e5086f9b8
10 changed files with 259 additions and 137 deletions

View File

@ -566,6 +566,8 @@ add_executable(supertuxkart
src/tracks/track_object.hpp src/tracks/track_object.hpp
src/tracks/track_object_manager.cpp src/tracks/track_object_manager.cpp
src/tracks/track_object_manager.hpp src/tracks/track_object_manager.hpp
src/tracks/track_sector.cpp
src/tracks/track_sector.hpp
src/tutorial/tutorial.cpp src/tutorial/tutorial.cpp
src/tutorial/tutorial_data.cpp src/tutorial/tutorial_data.cpp
src/tutorial/tutorial_data.hpp src/tutorial/tutorial_data.hpp

View File

@ -434,6 +434,8 @@ supertuxkart_SOURCES = \
tracks/track_object.hpp \ tracks/track_object.hpp \
tracks/track_object_manager.cpp \ tracks/track_object_manager.cpp \
tracks/track_object_manager.hpp \ tracks/track_object_manager.hpp \
tracks/track_sector.cpp \
tracks/track_sector.hpp \
tutorial/tutorial.cpp \ tutorial/tutorial.cpp \
tutorial/tutorial.hpp \ tutorial/tutorial.hpp \
tutorial/tutorial_data.cpp \ tutorial/tutorial_data.cpp \

View File

@ -874,6 +874,10 @@
RelativePath="..\..\tracks\track_object_manager.cpp" RelativePath="..\..\tracks\track_object_manager.cpp"
> >
</File> </File>
<File
RelativePath="..\..\tracks\track_sector.cpp"
>
</File>
</Filter> </Filter>
<Filter <Filter
Name="replay" Name="replay"
@ -1912,6 +1916,10 @@
RelativePath="..\..\tracks\track_object_manager.hpp" RelativePath="..\..\tracks\track_object_manager.hpp"
> >
</File> </File>
<File
RelativePath="..\..\tracks\track_sector.hpp"
>
</File>
</Filter> </Filter>
<Filter <Filter
Name="replay" Name="replay"

View File

@ -28,8 +28,9 @@ float RubberBall::m_st_interval;
float RubberBall::m_st_squash_duration; float RubberBall::m_st_squash_duration;
float RubberBall::m_st_squash_slowdown; float RubberBall::m_st_squash_slowdown;
RubberBall::RubberBall(Kart *kart) : Flyable(kart, PowerupManager::POWERUP_RUBBERBALL, RubberBall::RubberBall(Kart *kart)
0.0f /* mass */) : Flyable(kart, PowerupManager::POWERUP_RUBBERBALL, 0.0f /* mass */),
TrackSector()
{ {
float forw_offset = 0.5f*kart->getKartLength() + m_extend.getZ()*0.5f+5.0f; float forw_offset = 0.5f*kart->getKartLength() + m_extend.getZ()*0.5f+5.0f;
@ -62,13 +63,15 @@ RubberBall::RubberBall(Kart *kart) : Flyable(kart, PowerupManager::POWERUP_RUBBE
// Get 4 points for the interpolation // Get 4 points for the interpolation
int pred = QuadGraph::get()->getNode(m_current_graph_node) int pred = QuadGraph::get()->getNode(m_current_graph_node)
.getPredecessor(); .getPredecessor();
m_aiming_points[0] = QuadGraph::get()->getQuadOfNode(pred).getCenter(); m_aiming_points[0] = QuadGraph::get()->getQuadOfNode(pred).getCenter();
m_aiming_points[1] = QuadGraph::get()->getQuadOfNode(m_current_graph_node) m_aiming_points[1] = QuadGraph::get()->getQuadOfNode(m_current_graph_node)
.getCenter(); .getCenter();
m_aiming_points[2] = QuadGraph::get()->getQuadOfNode(m_aimed_graph_node).getCenter(); m_aiming_points[2] = QuadGraph::get()->getQuadOfNode(m_aimed_graph_node)
.getCenter();
int succ_succ = getSuccessorToHitTarget(m_aimed_graph_node); int succ_succ = getSuccessorToHitTarget(m_aimed_graph_node);
m_aiming_points[3] = QuadGraph::get()->getQuadOfNode(succ_succ).getCenter(); m_aiming_points[3] = QuadGraph::get()->getQuadOfNode(succ_succ)
.getCenter();
m_t = 0; m_t = 0;
m_t_increase = 1.0f/(m_aiming_points[2]-m_aiming_points[1]).length(); m_t_increase = 1.0f/(m_aiming_points[2]-m_aiming_points[1]).length();
@ -172,16 +175,18 @@ void RubberBall::update(float dt)
int indx = getSuccessorToHitTarget(m_current_graph_node); int indx = getSuccessorToHitTarget(m_current_graph_node);
// Determine new distance along track // Determine new distance along track
TrackSector::update(next_xyz);
Vec3 ball_distance_vec; Vec3 ball_distance_vec;
QuadGraph::get()->findRoadSector(next_xyz, &m_current_graph_node); QuadGraph::get()->findRoadSector(next_xyz, &m_current_graph_node);
if(m_current_graph_node == QuadGraph::UNKNOWN_SECTOR) if(m_current_graph_node == QuadGraph::UNKNOWN_SECTOR)
{ {
m_current_graph_node = m_current_graph_node =
QuadGraph::get()->findOutOfRoadSector(next_xyz, QuadGraph::get()->findOutOfRoadSector(next_xyz,
QuadGraph::UNKNOWN_SECTOR ); QuadGraph::UNKNOWN_SECTOR );
} }
QuadGraph::get()->spatialToTrack(&ball_distance_vec, getXYZ(), QuadGraph::get()->spatialToTrack(&ball_distance_vec, getXYZ(),
m_current_graph_node); m_current_graph_node);
// Detect wrap around, i.e. crossing the start line // Detect wrap around, i.e. crossing the start line
float old_distance = m_distance_along_track; float old_distance = m_distance_along_track;

View File

@ -21,6 +21,7 @@
#define HEADER_RUBBER_BALL_HPP #define HEADER_RUBBER_BALL_HPP
#include "items/flyable.hpp" #include "items/flyable.hpp"
#include "tracks/track_sector.hpp"
class Kart; class Kart;
class QuadGraph; class QuadGraph;
@ -28,7 +29,7 @@ class QuadGraph;
/** /**
* \ingroup items * \ingroup items
*/ */
class RubberBall: public Flyable class RubberBall: public Flyable, public TrackSector
{ {
private: private:
/** A class variable to store the default interval size. */ /** A class variable to store the default interval size. */

View File

@ -25,6 +25,7 @@
#include "audio/sfx_manager.hpp" #include "audio/sfx_manager.hpp"
#include "network/network_manager.hpp" #include "network/network_manager.hpp"
#include "race/history.hpp" #include "race/history.hpp"
#include "tracks/track_sector.hpp"
#include "tracks/track.hpp" #include "tracks/track.hpp"
#include "utils/constants.hpp" #include "utils/constants.hpp"
#include "utils/string_utils.hpp" #include "utils/string_utils.hpp"
@ -61,31 +62,7 @@ void LinearWorld::init()
for(unsigned int n=0; n<kart_amount; n++) for(unsigned int n=0; n<kart_amount; n++)
{ {
KartInfo info; KartInfo info;
info.m_track_sector = QuadGraph::UNKNOWN_SECTOR; info.getSector()->update(m_karts[n]->getXYZ());
info.m_last_valid_sector = 0;
info.m_lap_start_time = 0;
QuadGraph::get()->findRoadSector(m_karts[n]->getXYZ(),
&info.m_track_sector);
//If m_track_sector == UNKNOWN_SECTOR, then the kart is not on top of
//the road, so we have to use another function to find the sector.
info.m_on_road = info.m_track_sector != QuadGraph::UNKNOWN_SECTOR;
if (!info.m_on_road)
{
info.m_track_sector =
QuadGraph::get()->findOutOfRoadSector(m_karts[n]->getXYZ(),
QuadGraph::UNKNOWN_SECTOR );
}
QuadGraph::get()->spatialToTrack(&info.m_curr_track_coords,
m_karts[n]->getXYZ(),
info.m_track_sector );
info.m_race_lap = -1;
info.m_lap_start_time = 0;
info.m_time_at_last_lap = 99999.9f;
info.m_estimated_finish = -1.0f;
m_kart_info.push_back(info); m_kart_info.push_back(info);
} // next kart } // next kart
@ -114,29 +91,8 @@ void LinearWorld::restartRace()
const unsigned int kart_amount = m_karts.size(); const unsigned int kart_amount = m_karts.size();
for(unsigned int i=0; i<kart_amount; i++) for(unsigned int i=0; i<kart_amount; i++)
{ {
KartInfo& info = m_kart_info[i]; m_kart_info[i].reset();
info.m_track_sector = QuadGraph::UNKNOWN_SECTOR; m_kart_info[i].getSector()->update(m_karts[i]->getXYZ());
info.m_last_valid_sector = 0;
info.m_lap_start_time = 0;
QuadGraph::get()->findRoadSector(m_karts[i]->getXYZ(),
&info.m_track_sector);
//If m_track_sector == UNKNOWN_SECTOR, then the kart is not on top of
//the road, so we have to use another function to find the sector.
info.m_on_road = info.m_track_sector != QuadGraph::UNKNOWN_SECTOR;
if (!info.m_on_road)
{
info.m_track_sector =
QuadGraph::get()->findOutOfRoadSector(m_karts[i]->getXYZ(),
QuadGraph::UNKNOWN_SECTOR);
}
QuadGraph::get()->spatialToTrack(&info.m_curr_track_coords,
m_karts[i]->getXYZ(),
info.m_track_sector );
info.m_race_lap = -1;
info.m_lap_start_time = -0;
info.m_time_at_last_lap = 99999.9f;
} // next kart } // next kart
// First all kart infos must be updated before the kart position can be // First all kart infos must be updated before the kart position can be
@ -193,30 +149,7 @@ void LinearWorld::update(float dt)
// Nothing to do for karts that are currently being rescued or eliminated // Nothing to do for karts that are currently being rescued or eliminated
if(kart->playingEmergencyAnimation()) continue; if(kart->playingEmergencyAnimation()) continue;
// ---------- deal with sector data --------- kart_info.getSector()->update(kart->getXYZ());
// update sector variables
int prev_sector = kart_info.m_track_sector;
QuadGraph::get()->findRoadSector(kart->getXYZ(),
&kart_info.m_track_sector);
kart_info.m_on_road = kart_info.m_track_sector != QuadGraph::UNKNOWN_SECTOR;
if(kart_info.m_on_road)
{
kart_info.m_last_valid_sector = kart_info.m_track_sector;
}
else
{
// Kart off road. Find the closest sector instead.
kart_info.m_track_sector =
QuadGraph::get()->findOutOfRoadSector(kart->getXYZ(), prev_sector );
}
// Update track coords (=progression)
QuadGraph::get()->spatialToTrack(&kart_info.m_curr_track_coords,
kart->getXYZ(),
kart_info.m_track_sector );
} // for n } // for n
// Update all positions. This must be done after _all_ karts have // Update all positions. This must be done after _all_ karts have
@ -390,7 +323,7 @@ void LinearWorld::newLap(unsigned int kart_index)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
int LinearWorld::getSectorForKart(const int kart_id) const int LinearWorld::getSectorForKart(const int kart_id) const
{ {
return m_kart_info[kart_id].m_track_sector; return m_kart_info[kart_id].getSector()->getCurrentGraphNode();
} // getSectorForKart } // getSectorForKart
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -400,7 +333,7 @@ int LinearWorld::getSectorForKart(const int kart_id) const
*/ */
float LinearWorld::getDistanceDownTrackForKart(const int kart_id) const float LinearWorld::getDistanceDownTrackForKart(const int kart_id) const
{ {
return m_kart_info[kart_id].m_curr_track_coords.getZ(); return m_kart_info[kart_id].getSector()->getDistanceFromStart();
} // getDistanceDownTrackForKart } // getDistanceDownTrackForKart
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -410,7 +343,7 @@ float LinearWorld::getDistanceDownTrackForKart(const int kart_id) const
*/ */
float LinearWorld::getDistanceToCenterForKart(const int kart_id) const float LinearWorld::getDistanceToCenterForKart(const int kart_id) const
{ {
return m_kart_info[kart_id].m_curr_track_coords.getX(); return m_kart_info[kart_id].getSector()->getDistanceToCenter();
} // getDistanceToCenterForKart } // getDistanceToCenterForKart
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -566,31 +499,13 @@ void LinearWorld::moveKartAfterRescue(Kart* kart)
{ {
KartInfo& info = m_kart_info[kart->getWorldKartId()]; KartInfo& info = m_kart_info[kart->getWorldKartId()];
// If the kart is off road, rescue it to the last valid track position info.getSector()->rescue();
// instead of the current one (since the sector might be determined by int sector = info.getSector()->getCurrentGraphNode();
// being closest to it, which allows shortcuts like drive towards another kart->setXYZ( QuadGraph::get()
// part of the lap, press rescue, and be rescued to this other part of ->getQuadOfNode(sector).getCenter());
// the track (example: math class, drive towards the left after start,
// when hitting the books, press rescue --> you are rescued to the
// end of the track).
if(!info.m_on_road)
{
info.m_track_sector = info.m_last_valid_sector;
}
// Using the predecessor has the additional afvantage (besides punishing
// the player a bit more) that it makes it less likely to fall in a
// rescue loop since the kart moves back on each attempt.
info.m_track_sector = QuadGraph::get()->getNode(info.m_track_sector)
.getPredecessor();
info.m_last_valid_sector= QuadGraph::get()->getNode(info.m_track_sector)
.getPredecessor();
kart->setXYZ( QuadGraph::get()->getQuadOfNode(info.m_track_sector)
.getCenter());
btQuaternion heading(btVector3(0.0f, 1.0f, 0.0f), btQuaternion heading(btVector3(0.0f, 1.0f, 0.0f),
m_track->getAngle(info.m_track_sector) ); m_track->getAngle(sector) );
kart->setRotation(heading); kart->setRotation(heading);
// A certain epsilon is added here to the Z coordinate, in case // A certain epsilon is added here to the Z coordinate, in case
@ -602,7 +517,7 @@ void LinearWorld::moveKartAfterRescue(Kart* kart)
btTransform pos; btTransform pos;
pos.setOrigin(kart->getXYZ()+btVector3(0, kart->getKartHeight() + epsilon, 0)); pos.setOrigin(kart->getXYZ()+btVector3(0, kart->getKartHeight() + epsilon, 0));
pos.setRotation(btQuaternion(btVector3(0.0f, 1.0f, 0.0f), pos.setRotation(btQuaternion(btVector3(0.0f, 1.0f, 0.0f),
m_track->getAngle(info.m_track_sector))); m_track->getAngle(sector)));
kart->getBody()->setCenterOfMassTransform(pos); kart->getBody()->setCenterOfMassTransform(pos);
@ -815,19 +730,20 @@ void LinearWorld::updateRacePosition()
void LinearWorld::checkForWrongDirection(unsigned int i) void LinearWorld::checkForWrongDirection(unsigned int i)
{ {
if(!m_karts[i]->getController()->isPlayerController()) return; if(!m_karts[i]->getController()->isPlayerController()) return;
if(!m_kart_info[i].m_on_road || if(!m_kart_info[i].getSector()->isOnRoad()||
m_karts[i]->playingEmergencyAnimation()) return; m_karts[i]->playingEmergencyAnimation()) return;
const Kart *kart=m_karts[i]; const Kart *kart=m_karts[i];
// If the kart can go in more than one directions from the current track // If the kart can go in more than one directions from the current track
// don't do any reverse message handling, since it is likely that there // don't do any reverse message handling, since it is likely that there
// will be one direction in which it isn't going backwards anyway. // will be one direction in which it isn't going backwards anyway.
if(QuadGraph::get()->getNumberOfSuccessors(m_kart_info[i].m_track_sector)>1) int sector = m_kart_info[i].getSector()->getCurrentGraphNode();
if(QuadGraph::get()->getNumberOfSuccessors(sector)>1)
return; return;
// check if the player is going in the wrong direction // check if the player is going in the wrong direction
float angle_diff = kart->getHeading() - float angle_diff = kart->getHeading() -
m_track->getAngle(m_kart_info[i].m_track_sector); m_track->getAngle(sector);
if(angle_diff > M_PI) angle_diff -= 2*M_PI; if(angle_diff > M_PI) angle_diff -= 2*M_PI;
else if (angle_diff < -M_PI) angle_diff += 2*M_PI; else if (angle_diff < -M_PI) angle_diff += 2*M_PI;
// Display a warning message if the kart is going back way (unless // Display a warning message if the kart is going back way (unless

View File

@ -21,6 +21,7 @@
#include <vector> #include <vector>
#include "modes/world_with_rank.hpp" #include "modes/world_with_rank.hpp"
#include "tracks/track_sector.hpp"
#include "utils/aligned_array.hpp" #include "utils/aligned_array.hpp"
class SFXBase; class SFXBase;
@ -33,6 +34,7 @@ class SFXBase;
*/ */
class LinearWorld : public WorldWithRank class LinearWorld : public WorldWithRank
{ {
private:
/** Sfx for the final lap. */ /** Sfx for the final lap. */
SFXBase *m_last_lap_sfx; SFXBase *m_last_lap_sfx;
@ -41,27 +43,48 @@ class LinearWorld : public WorldWithRank
bool m_last_lap_sfx_playing; bool m_last_lap_sfx_playing;
private: // ------------------------------------------------------------------------
/** Some additional info that needs to be kept for each kart /** Some additional info that needs to be kept for each kart
* in this kind of race. * in this kind of race.
*/ */
struct KartInfo class KartInfo
{ {
int m_race_lap; /**<Number of finished(!) laps. */ public:
float m_time_at_last_lap; /**<Time at finishing last lap. */ /** Number of finished(!) laps. */
float m_lap_start_time; /**<Time at start of a new lap. */ int m_race_lap;
float m_estimated_finish; /**<During last lap only:
* estimated finishing time! */
int m_track_sector; /**<Index in driveline, special values
* e.g. UNKNOWN_SECTOR can be negative!*/
int m_last_valid_sector; /* used when rescusing, e.g. for invalid shortcuts */ /** Time at finishing last lap. */
float m_time_at_last_lap;
Vec3 m_curr_track_coords; /** Time at start of a new lap. */
/** True if the kart is on top of the road path drawn by the drivelines */ float m_lap_start_time;
bool m_on_road;
/** During last lap only: estimated finishing time! */
float m_estimated_finish;
/** Stores the current graph node and track coordinates etc. */
TrackSector m_current_sector;
/** Initialises all fields. */
KartInfo() { reset(); }
// --------------------------------------------------------------------
/** Re-initialises all data. */
void reset()
{
m_race_lap = -1;
m_lap_start_time = 0;
m_time_at_last_lap = 99999.9f;
m_estimated_finish = -1.0f;
m_current_sector.reset();
}
// --------------------------------------------------------------------
/** Returns a pointer to the current node object. */
TrackSector *getSector() {return &m_current_sector; }
// --------------------------------------------------------------------
/** Returns a pointer to the current node object. */
const TrackSector *getSector() const {return &m_current_sector; }
}; };
// ------------------------------------------------------------------------
protected: protected:
RaceGUIBase::KartIconDisplayInfo* m_kart_display_info; RaceGUIBase::KartIconDisplayInfo* m_kart_display_info;
@ -101,17 +124,19 @@ public:
getKartsDisplayInfo(); getKartsDisplayInfo();
virtual void moveKartAfterRescue(Kart* kart); virtual void moveKartAfterRescue(Kart* kart);
virtual void restartRace(); virtual void restartRace();
virtual bool raceHasLaps(){ return true; }
virtual void newLap(unsigned int kart_index); virtual void newLap(unsigned int kart_index);
virtual bool haveBonusBoxes(){ return true; }
// ------------------------------------------------------------------------
/** Returns if this race mode has laps. */
virtual bool raceHasLaps(){ return true; }
// ------------------------------------------------------------------------
/** Returns if this race mode has bonus items. */
virtual bool haveBonusBoxes(){ return true; }
// ------------------------------------------------------------------------
/** Returns true if the kart is on a valid driveline quad. /** Returns true if the kart is on a valid driveline quad.
* \param kart_index Index of the kart. * \param kart_index Index of the kart. */
*/
bool isOnRoad(unsigned int kart_index) const bool isOnRoad(unsigned int kart_index) const
{ return m_kart_info[kart_index].m_on_road; } { return m_kart_info[kart_index].getSector()->isOnRoad(); }
}; // LinearWorld }; // LinearWorld
#endif #endif

View File

@ -516,12 +516,9 @@ void QuadGraph::spatialToTrack(Vec3 *dst, const Vec3& xyz,
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** findRoadSector returns in which sector on the road the position /** findRoadSector returns in which sector on the road the position
* xyz is. If xyz is not on top of the road, it returns * xyz is. If xyz is not on top of the road, it sets UNKNOWN_SECTOR as sector.
* UNKNOWN_SECTOR.
* *
* The 'sector' could be defined as the number of the closest track * \param xyz Position for which the segment should be determined.
* segment to XYZ.
* \param XYZ Position for which the segment should be determined.
* \param sector Contains the previous sector (as a shortcut, since usually * \param sector Contains the previous sector (as a shortcut, since usually
* the sector is the same as the last one), and on return the result * the sector is the same as the last one), and on return the result
* \param all_sectors If this is not NULL, it is a list of all sectors to * \param all_sectors If this is not NULL, it is a list of all sectors to
@ -565,7 +562,7 @@ void QuadGraph::findRoadSector(const Vec3& xyz, int *sector,
indx = indx<(int)m_all_nodes.size()-1 ? indx +1 : 0; indx = indx<(int)m_all_nodes.size()-1 ? indx +1 : 0;
const Quad &q = getQuadOfNode(indx); const Quad &q = getQuadOfNode(indx);
float dist = xyz.getY() - q.getMinHeight(); float dist = xyz.getY() - q.getMinHeight();
// While negative distances are unlikely, we allow some small netative // While negative distances are unlikely, we allow some small negative
// numbers in case that the kart is partly in the track. // numbers in case that the kart is partly in the track.
if(q.pointInQuad(xyz) && dist < min_dist && dist>-1.0f) if(q.pointInQuad(xyz) && dist < min_dist && dist>-1.0f)
{ {

View File

@ -0,0 +1,91 @@
// $Id$
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2011 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 "tracks/track_sector.hpp"
#include "tracks/quad_graph.hpp"
// ----------------------------------------------------------------------------
/** Initialises the object, and sets the current graph node to be undefined.
*/
TrackSector::TrackSector()
{
reset();
} // TrackSector
// ----------------------------------------------------------------------------
void TrackSector::reset()
{
m_current_graph_node = QuadGraph::UNKNOWN_SECTOR;
m_last_valid_graph_node = QuadGraph::UNKNOWN_SECTOR;
m_on_road = false;
} // reset
// ----------------------------------------------------------------------------
/** Updates the current graph node index, and the track coordinates for
* the specified point.
* \param xyz The new coordinates to search the graph node for.
*/
void TrackSector::update(const Vec3 &xyz)
{
int prev_sector = m_current_graph_node;
QuadGraph::get()->findRoadSector(xyz, &m_current_graph_node);
m_on_road = m_current_graph_node != QuadGraph::UNKNOWN_SECTOR;
// If m_track_sector == UNKNOWN_SECTOR, then the kart is not on top of
// the road, so we have to use search for the closest graph node.
if(m_current_graph_node == QuadGraph::UNKNOWN_SECTOR)
{
m_current_graph_node =
QuadGraph::get()->findOutOfRoadSector(xyz,
prev_sector);
}
else
m_last_valid_graph_node = m_current_graph_node;
// Now determine the 'track' coords, i.e. ow far from the start of the
// track, and how far to the left or right of the center driveline.
QuadGraph::get()->spatialToTrack(&m_current_track_coords, xyz,
m_current_graph_node);
} // update
// ----------------------------------------------------------------------------
void TrackSector::rescue()
{
// If the kart is off road, rescue it to the last valid track position
// instead of the current one (since the sector might be determined by
// being closest to it, which allows shortcuts like drive towards another
// part of the lap, press rescue, and be rescued to this other part of
// the track (example: math class, drive towards the left after start,
// when hitting the books, press rescue --> you are rescued to the
// end of the track).
if(!isOnRoad())
{
m_current_graph_node = m_last_valid_graph_node;
}
// Using the predecessor has the additional advantage (besides punishing
// the player a bit more) that it makes it less likely to fall in a
// rescue loop since the kart moves back on each attempt.
m_current_graph_node = QuadGraph::get()->getNode(m_current_graph_node)
.getPredecessor();
m_last_valid_graph_node = QuadGraph::get()->getNode(m_current_graph_node)
.getPredecessor();
} // rescue

View File

@ -0,0 +1,75 @@
// $Id$
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2011 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_TRACK_SECTOR_HPP
#define HEADER_TRACK_SECTOR_HPP
#include "utils/vec3.hpp"
/** This object keeps track of which sector an object is on. A sector is
* actually just the graph node (it's called sector to better distinguish
* the graph node from say xml node and scene node).
* An object that has a track sector can determine how far away it is from
* the start line, how far away it is from the center driveline. If the
* object is not actually on part of the quad graph, it will determine the
* closest sector it is to, and set a flag (!isOnRoad).
* This object will also keep track on the last valid sector an object was
* on, which is used to reset a kart in case of a rescue.
*/
class TrackSector
{
private:
/** The graph node the object is on. */
int m_current_graph_node;
/** The index of the last valid graph node. */
int m_last_valid_graph_node;
/** The coordinates of this object on the track, i.e. how far from
* the start of the track, and how far to the left or right
* of the center driveline. */
Vec3 m_current_track_coords;
/** True if the object is on the road (driveline), or not. */
bool m_on_road;
public:
TrackSector();
void reset();
void rescue();
void update(const Vec3 &xyz);
// ------------------------------------------------------------------------
/** Returns how far the the object is from the start line. */
float getDistanceFromStart() const { return m_current_track_coords.getZ();}
// ------------------------------------------------------------------------
/** Returns the distance to the centre driveline. */
float getDistanceToCenter() const { return m_current_track_coords.getX(); }
// ------------------------------------------------------------------------
/** Returns the current graph node. */
int getCurrentGraphNode() const {return m_current_graph_node;}
// ------------------------------------------------------------------------
/** Returns if this object is on the road (driveline). */
bool isOnRoad() const { return m_on_road; }
}; // TrackSector
#endif