Improved shortcut handling:

1) on road/off road is now detected with a certain tolerance
   to the drivelines (currently 15%), i.e. the drivelines are
   made 15% wider.
2) Skipped segments distance was shortened to 50m (since it
   should be used less with the above higher tolerance, and
   it caused problems with shortcut not being detected.
3) The new drivelines with tolerance can be seen with --track-debug=4
   (--track-debug=2 shows the original drivelines)


git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/trunk/supertuxkart@2890 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk 2009-01-13 00:16:09 +00:00
parent bddf82e272
commit 2c0a135d94
7 changed files with 79 additions and 25 deletions

View File

@ -39,8 +39,9 @@
(zipper-force 250.0 ) ;; additional zipper force
(zipper-speed-gain 4.5 ) ;; one time additional speed
(shortcut-length 120 ) ;; leaving the road and coming back on it more than
(shortcut-length 50 ) ;; leaving the road and coming back on it more than
;; x 'meters" later is considered to be a shortcut
(offroad-tolerance 0.15) ;; Widen the road 15% for shortcut detection.
(enable_networking #f ) ;; For now disable networking
(explosion-impulse 10000.0 ) ;; explosion impulse on not directly hit karts
(explosion-impulse-objects 500.0) ;; explosion impulse for physics objects (smaller

View File

@ -451,12 +451,13 @@ void InitTuxkart()
highscore_manager = new HighscoreManager ();
grand_prix_manager = new GrandPrixManager ();
network_manager = new NetworkManager ();
stk_config->load(file_manager->getConfigFile("stk_config.data"));
track_manager->loadTrackList();
// Check needs GP and track manager.
// unlock_manager->check needs GP and track manager.
unlock_manager->check();
sound_manager->addMusicToTracks();
stk_config->load(file_manager->getConfigFile("stk_config.data"));
race_manager = new RaceManager ();
// default settings for Quickstart
race_manager->setNumPlayers(1);

View File

@ -149,8 +149,9 @@ void LinearWorld::update(float delta)
// update sector variables
int prev_sector = kart_info.m_track_sector;
m_track->findRoadSector( kart->getXYZ(), &kart_info.m_track_sector);
m_track->findRoadSector( kart->getXYZ(), &kart_info.m_track_sector,
/*tolerance*/ true);
// Check if the kart is taking a shortcut (if it's not already doing one):
// -----------------------------------------------------------------------
kart_info.m_on_road = kart_info.m_track_sector != Track::UNKNOWN_SECTOR;

View File

@ -108,6 +108,7 @@ void STKConfig::load(const std::string &filename)
CHECK_NEG(m_zipper_force, "zipper-force" );
CHECK_NEG(m_zipper_speed_gain, "zipper-speed-gain" );
CHECK_NEG(m_shortcut_length, "shortcut-length" );
CHECK_NEG(m_offroad_tolerance, "offroad-tolerance" );
CHECK_NEG(m_explosion_impulse, "explosion-impulse" );
CHECK_NEG(m_explosion_impulse_objects, "explosion-impulse-objects" );
CHECK_NEG(m_max_history, "max-history" );
@ -135,7 +136,7 @@ void STKConfig::init_defaults()
m_explosion_impulse = m_explosion_impulse_objects =
m_shortcut_length = m_music_credit_time =
m_delay_finish_time = m_skid_fadeout_time =
m_slowdown_factor =
m_slowdown_factor = m_offroad_tolerance =
UNDEFINED;
m_max_karts = -100;
m_grid_order = -100;
@ -175,7 +176,8 @@ void STKConfig::getAllData(const lisp::Lisp* lisp)
// Get the values which are not part of the default KartProperties
// ---------------------------------------------------------------
lisp->get("anvil-weight", m_anvil_weight );
lisp->get("shortcut-length", m_shortcut_length );
lisp->get("shortcut-length", m_shortcut_length );
lisp->get("offroad-tolerance", m_offroad_tolerance );
lisp->get("anvil-speed-factor", m_anvil_speed_factor );
lisp->get("parachute-friction", m_parachute_friction );
lisp->get("parachute-time", m_parachute_time );

View File

@ -55,6 +55,9 @@ public:
float m_zipper_speed_gain; /**<Initial one time speed gain. */
float m_shortcut_length; /**<Skipping more than this distance
in segments triggers a shortcut. */
float m_offroad_tolerance; /**<Road width is extended by that
fraction to make shortcut detection
more forgiving. */
float m_explosion_impulse; /**<Impulse affecting each non-hit kart.*/
float m_explosion_impulse_objects;/**<Impulse of explosion on moving
objects, e.g. road cones, ... */

View File

@ -141,17 +141,37 @@ int Track::pointInQuad
*
* The 'sector' could be defined as the number of the closest track
* segment to XYZ.
* \param XYZ Position for which the segment should be determined.
* \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
* \param with_tolerance If true, the drivelines with tolerance are used.
* This reduces the impact of driving slightly off road.
*/
void Track::findRoadSector(const Vec3& XYZ, int *sector )const
void Track::findRoadSector(const Vec3& XYZ, int *sector,
bool with_tolerance )const
{
if(*sector!=UNKNOWN_SECTOR)
{
int next = (unsigned)(*sector) + 1 < m_left_driveline.size() ? *sector + 1 : 0;
if(pointInQuad( m_left_driveline[*sector], m_right_driveline[*sector],
m_right_driveline[next], m_left_driveline[next],
XYZ ) != QUAD_TRI_NONE)
// Still in the same sector, no changes
return;
if(with_tolerance)
{
if(pointInQuad(m_dl_with_tolerance_left[*sector],
m_dl_with_tolerance_right[*sector],
m_dl_with_tolerance_right[next],
m_dl_with_tolerance_left[next],
XYZ ) != QUAD_TRI_NONE)
// Still in the same sector, no changes
return;
}
else
{
if(pointInQuad(m_left_driveline[*sector],
m_right_driveline[*sector],
m_right_driveline[next],
m_left_driveline[next], XYZ ) != QUAD_TRI_NONE)
// Still in the same sector, no changes
return;
}
}
/* To find in which 'sector' of the track the kart is, we use a
'point in triangle' algorithm for each triangle in the quad
@ -165,9 +185,14 @@ void Track::findRoadSector(const Vec3& XYZ, int *sector )const
for( size_t i = 0; i < DRIVELINE_SIZE ; ++i )
{
next = (unsigned int)i + 1 < DRIVELINE_SIZE ? (int)i + 1 : 0;
triangle = pointInQuad( m_left_driveline[i], m_right_driveline[i],
m_right_driveline[next], m_left_driveline[next],
XYZ );
triangle = with_tolerance
? pointInQuad(m_dl_with_tolerance_left[i],
m_dl_with_tolerance_right[i],
m_dl_with_tolerance_right[next],
m_dl_with_tolerance_left[next], XYZ )
: pointInQuad(m_left_driveline[i], m_right_driveline[i],
m_right_driveline[next], m_left_driveline[next],
XYZ );
if (triangle != QUAD_TRI_NONE && ((XYZ.getZ()-m_left_driveline[i].getZ()) < 1.0f))
{
@ -202,6 +227,9 @@ void Track::findRoadSector(const Vec3& XYZ, int *sector )const
segment = possible_segment_tris[i].segment;
next = segment + 1 < DRIVELINE_SIZE ? (int)segment + 1 : 0;
// Note: we can make the plane with the normal driveliens
// (not the one with tolerance), since the driveliens with
// tolerance lie in the same plane.
if( possible_segment_tris[i].triangle == QUAD_TRI_FIRST )
{
sgMakePlane( plane, m_left_driveline[segment].toFloat(),
@ -500,20 +528,25 @@ void Track::addDebugToScene(int type) const
scene->add(sphere);
} // for i
} /// type ==1
if(type&2)
// 2: drivelines, 4: driveline with tolerance
if(type&6)
{
ssgVertexArray* v_array = new ssgVertexArray();
ssgColourArray* c_array = new ssgColourArray();
const std::vector<Vec3> &left = type&2 ? m_left_driveline
: m_dl_with_tolerance_left;
const std::vector<Vec3> &right = type&2 ? m_right_driveline
: m_dl_with_tolerance_right;
for(unsigned int i = 0; i < m_driveline.size(); i++)
{
int ip1 = i==m_driveline.size()-1 ? 0 : i+1;
// The segment display must be slightly higher than the
// track, otherwise it's not clearly visible.
sgVec3 v;
sgCopyVec3(v,m_left_driveline [i ].toFloat()); v[2]+=0.1f; v_array->add(v);
sgCopyVec3(v,m_right_driveline[i ].toFloat()); v[2]+=0.1f; v_array->add(v);
sgCopyVec3(v,m_right_driveline[ip1].toFloat()); v[2]+=0.1f; v_array->add(v);
sgCopyVec3(v,m_left_driveline [ip1].toFloat()); v[2]+=0.1f; v_array->add(v);
sgCopyVec3(v,left [i ].toFloat()); v[2]+=0.1f; v_array->add(v);
sgCopyVec3(v,right[i ].toFloat()); v[2]+=0.1f; v_array->add(v);
sgCopyVec3(v,right[ip1].toFloat()); v[2]+=0.1f; v_array->add(v);
sgCopyVec3(v,left [ip1].toFloat()); v[2]+=0.1f; v_array->add(v);
sgVec4 vc;
vc[0] = i%2==0 ? 1.0f : 0.0f;
vc[1] = 1.0f-v[0];
@ -902,8 +935,7 @@ void Track::startMusic() const {
} // startMusic
//-----------------------------------------------------------------------------
void
Track::loadDriveline()
void Track::loadDriveline()
{
readDrivelineFromFile(m_left_driveline, ".drvl");
@ -917,6 +949,8 @@ Track::loadDriveline()
"and the left driveline is " << m_left_driveline.size()
<< " vertex long. Track is " << m_name << " ." << std::endl;
m_dl_with_tolerance_left.reserve(DRIVELINE_SIZE);
m_dl_with_tolerance_right.reserve(DRIVELINE_SIZE);
m_driveline.reserve(DRIVELINE_SIZE);
m_path_width.reserve(DRIVELINE_SIZE);
m_angle.reserve(DRIVELINE_SIZE);
@ -927,6 +961,13 @@ Track::loadDriveline()
float width = ( m_right_driveline[i] - center_point ).length();
m_path_width.push_back(width);
// Compute the drivelines with tolerance
Vec3 diff = (m_left_driveline[i] - m_right_driveline[i])
* stk_config->m_offroad_tolerance;
m_dl_with_tolerance_left.push_back(m_left_driveline[i]+diff);
m_dl_with_tolerance_right.push_back(m_right_driveline[i]-diff);
}
for(unsigned int i = 0; i < DRIVELINE_SIZE; ++i)

View File

@ -97,7 +97,11 @@ public:
//FIXME: Maybe the next 4 vectors should be inside an struct and be used
//from a vector of structs?
//FIXME: should the driveline be set as a sgVec2?
std::vector<Vec3> m_driveline;
std::vector<Vec3> m_driveline;
/** Same as drivelines, but with stk_config->m_offroad_tolerance applied
* to widen the road (to make shortcut detection less severe). */
std::vector<Vec3> m_dl_with_tolerance_left;
std::vector<Vec3> m_dl_with_tolerance_right;
std::vector<SGfloat> m_distance_from_start;
std::vector<SGfloat> m_path_width;
std::vector<SGfloat> m_angle;
@ -134,7 +138,8 @@ public:
void drawScaled2D (float x, float y, float w,
float h ) const;
void findRoadSector (const Vec3& XYZ, int *sector) const;
void findRoadSector (const Vec3& XYZ, int *sector,
bool with_tolerance=false) const;
int findOutOfRoadSector(const Vec3& XYZ,
const RoadSide SIDE,
const int CURR_SECTOR