1) Removed some of the old driveline usage (not all yet, work
in progress). 2) Removed shortcut detection and handling. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/irrlicht@3505 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
@@ -101,7 +101,8 @@ Plunger::Plunger(Kart *kart) : Flyable(kart, POWERUP_PLUNGER)
|
||||
// -----------------------------------------------------------------------------
|
||||
Plunger::~Plunger()
|
||||
{
|
||||
m_rubber_band->removeFromScene();
|
||||
if(m_rubber_band)
|
||||
m_rubber_band->removeFromScene();
|
||||
} // ~Plunger
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
@@ -251,10 +251,6 @@ public:
|
||||
const std::string& getName () const {return m_kart_properties->getName();}
|
||||
const std::string& getIdent () const {return m_kart_properties->getIdent();}
|
||||
virtual bool isPlayerKart () const {return false; }
|
||||
/** Called by world in case of the kart taking a shortcut. The player kart
|
||||
* will display a message in this case, default behaviour is to do nothing.
|
||||
*/
|
||||
virtual void doingShortcut() {};
|
||||
// addMessages gets called by world to add messages to the gui
|
||||
virtual void addMessages () {};
|
||||
virtual void collectedItem (const Item &item, int random_attachment);
|
||||
|
||||
@@ -381,15 +381,3 @@ void PlayerKart::collectedItem(const Item &item, int add_info)
|
||||
}
|
||||
}
|
||||
} // collectedItem
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Called when the kart is doing a shortcut. The player kart will display
|
||||
* a message for the user.
|
||||
*/
|
||||
void PlayerKart::doingShortcut()
|
||||
{
|
||||
RaceGUI* m=(RaceGUI*)getRaceGUI();
|
||||
// Can happen if the option menu is called
|
||||
if(m)
|
||||
m->addMessage(_("Invalid short-cut!!"), this, 2.0f, 60);
|
||||
} // doingShortcut
|
||||
|
||||
@@ -63,7 +63,6 @@ public:
|
||||
virtual void crashed (Kart *k);
|
||||
virtual void setPosition (int p);
|
||||
virtual void raceFinished (float time);
|
||||
virtual void doingShortcut ();
|
||||
bool isPlayerKart () const {return true;}
|
||||
Camera* getCamera () {return m_camera;}
|
||||
void reset ();
|
||||
|
||||
@@ -149,23 +149,12 @@ 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,
|
||||
/*tolerance*/ true);
|
||||
m_track->findRoadSector( kart->getXYZ(), &kart_info.m_track_sector);
|
||||
|
||||
// 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;
|
||||
if(kart_info.m_on_road)
|
||||
{
|
||||
if(m_track->isShortcut(kart_info.m_last_valid_sector, kart_info.m_track_sector))
|
||||
{
|
||||
// bring karts back to where they left the track.
|
||||
rescueKartAfterShortcut(kart, kart_info);
|
||||
}
|
||||
kart_info.m_last_valid_sector = kart_info.m_track_sector;
|
||||
kart_info.m_last_valid_race_lap = kart_info.m_race_lap;
|
||||
} // last_valid_sectpr!=UNKNOWN_SECTOR
|
||||
else
|
||||
if(!kart_info.m_on_road)
|
||||
{
|
||||
// Kart off road. Find the closest sector instead.
|
||||
kart_info.m_track_sector =
|
||||
@@ -174,8 +163,6 @@ void LinearWorld::update(float delta)
|
||||
? Track::RS_RIGHT
|
||||
: Track::RS_LEFT,
|
||||
prev_sector );
|
||||
if(m_track->isShortcut(prev_sector, kart_info.m_track_sector))
|
||||
rescueKartAfterShortcut(kart, kart_info);
|
||||
}
|
||||
|
||||
// Update track coords (=progression)
|
||||
@@ -500,23 +487,6 @@ float LinearWorld::estimateFinishTimeForKart(Kart* kart)
|
||||
return getTime() + (full_distance - distance_covered) / average_speed;
|
||||
|
||||
} // estimateFinishTime
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Rescues a kart after a shortcut was detected. The kart is placed at the
|
||||
* last valid position.
|
||||
*/
|
||||
void LinearWorld::rescueKartAfterShortcut(Kart* kart, KartInfo& kart_info)
|
||||
{
|
||||
// Reset the kart to the segment where the shortcut started
|
||||
|
||||
// add one because 'moveKartAfterRescue' removes 1
|
||||
kart_info.m_track_sector = kart_info.m_last_valid_sector+1;
|
||||
if(kart_info.m_track_sector>=(int)m_track->m_driveline.size())
|
||||
kart_info.m_track_sector = 0;
|
||||
kart_info.m_race_lap = kart_info.m_last_valid_race_lap;
|
||||
|
||||
kart->doingShortcut();
|
||||
kart->forceRescue();
|
||||
} // rescueKartAfterShortcut
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Decide where to drop a rescued kart
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#include "modes/linear_world.hpp"
|
||||
#include "network/network_manager.hpp"
|
||||
#include "robots/track_info.hpp"
|
||||
#include "tracks/quad_graph.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
#include "utils/constants.hpp"
|
||||
|
||||
@@ -63,6 +64,21 @@ DefaultRobot::DefaultRobot(const std::string& kart_name,
|
||||
m_kart_length = m_kart_properties->getKartModel()->getLength();
|
||||
m_kart_width = m_kart_properties->getKartModel()->getWidth();
|
||||
m_track = RaceManager::getTrack();
|
||||
m_quad_graph = &m_track->getQuadGraph();
|
||||
m_next_quad_index.reserve(m_quad_graph->getNumNodes());
|
||||
m_successor_index.reserve(m_quad_graph->getNumNodes());
|
||||
|
||||
// For now pick one part on random, which is not adjusted during the run
|
||||
std::vector<unsigned int> next;
|
||||
for(unsigned int i=0; i<m_quad_graph->getNumNodes(); i++)
|
||||
{
|
||||
next.clear();
|
||||
m_quad_graph->getSuccessors(i, next);
|
||||
int indx = rand() % next.size();
|
||||
m_successor_index.push_back(indx);
|
||||
m_next_quad_index.push_back(next[indx]);
|
||||
}
|
||||
|
||||
m_world = dynamic_cast<LinearWorld*>(RaceManager::getWorld());
|
||||
assert(m_world != NULL);
|
||||
|
||||
@@ -304,9 +320,8 @@ void DefaultRobot::handleBraking()
|
||||
//-----------------------------------------------------------------------------
|
||||
void DefaultRobot::handleSteering(float dt)
|
||||
{
|
||||
const unsigned int DRIVELINE_SIZE = (unsigned int)m_track->m_driveline.size();
|
||||
const size_t NEXT_SECTOR = (unsigned int)m_track_sector + 1 < DRIVELINE_SIZE
|
||||
? m_track_sector + 1 : 0;
|
||||
const int next = m_next_quad_index[m_track_sector];
|
||||
|
||||
float steer_angle = 0.0f;
|
||||
|
||||
/*The AI responds based on the information we just gathered, using a
|
||||
@@ -316,7 +331,7 @@ void DefaultRobot::handleSteering(float dt)
|
||||
if( fabsf(m_world->getDistanceToCenterForKart( getWorldKartId() )) + 0.5f >
|
||||
m_track->getWidth()[m_track_sector] )
|
||||
{
|
||||
steer_angle = steerToPoint( m_track->m_driveline[NEXT_SECTOR], dt );
|
||||
steer_angle = steerToPoint(m_quad_graph->getCenterOfQuad(next), dt );
|
||||
|
||||
#ifdef AI_DEBUG
|
||||
std::cout << "- Outside of road: steer to center point." <<
|
||||
@@ -330,12 +345,12 @@ void DefaultRobot::handleSteering(float dt)
|
||||
//-1 = left, 1 = right, 0 = no crash.
|
||||
if( m_start_kart_crash_direction == 1 )
|
||||
{
|
||||
steer_angle = steerToAngle( NEXT_SECTOR, -M_PI*0.5f );
|
||||
steer_angle = steerToAngle(next, -M_PI*0.5f );
|
||||
m_start_kart_crash_direction = 0;
|
||||
}
|
||||
else if(m_start_kart_crash_direction == -1)
|
||||
{
|
||||
steer_angle = steerToAngle( NEXT_SECTOR, M_PI*0.5f);
|
||||
steer_angle = steerToAngle(next, M_PI*0.5f);
|
||||
m_start_kart_crash_direction = 0;
|
||||
}
|
||||
else
|
||||
@@ -343,12 +358,12 @@ void DefaultRobot::handleSteering(float dt)
|
||||
if(m_world->getDistanceToCenterForKart( getWorldKartId() ) >
|
||||
m_world->getDistanceToCenterForKart( m_crashes.m_kart ))
|
||||
{
|
||||
steer_angle = steerToAngle( NEXT_SECTOR, -M_PI*0.5f );
|
||||
steer_angle = steerToAngle(next, -M_PI*0.5f );
|
||||
m_start_kart_crash_direction = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
steer_angle = steerToAngle( NEXT_SECTOR, M_PI*0.5f );
|
||||
steer_angle = steerToAngle(next, M_PI*0.5f );
|
||||
m_start_kart_crash_direction = -1;
|
||||
}
|
||||
}
|
||||
@@ -367,20 +382,20 @@ void DefaultRobot::handleSteering(float dt)
|
||||
{
|
||||
case FT_FAREST_POINT:
|
||||
{
|
||||
Vec2 straight_point;
|
||||
findNonCrashingPoint( straight_point );
|
||||
Vec3 straight_point;
|
||||
findNonCrashingPoint(&straight_point);
|
||||
steer_angle = steerToPoint(straight_point, dt);
|
||||
}
|
||||
break;
|
||||
|
||||
case FT_PARALLEL:
|
||||
steer_angle = steerToAngle( NEXT_SECTOR, 0.0f );
|
||||
steer_angle = steerToAngle(next, 0.0f );
|
||||
break;
|
||||
|
||||
case FT_AVOID_TRACK_CRASH:
|
||||
if( m_crashes.m_road )
|
||||
{
|
||||
steer_angle = steerToAngle( m_track_sector, 0.0f );
|
||||
steer_angle = steerToAngle(m_track_sector, 0.0f );
|
||||
}
|
||||
else steer_angle = 0.0f;
|
||||
|
||||
@@ -736,12 +751,12 @@ float DefaultRobot::steerToAngle(const size_t SECTOR, const float ANGLE)
|
||||
* \param point Point to steer towards.
|
||||
* \param dt Time step.
|
||||
*/
|
||||
float DefaultRobot::steerToPoint(const Vec2 point, float dt)
|
||||
float DefaultRobot::steerToPoint(const Vec3 &point, float dt)
|
||||
{
|
||||
// No sense steering if we are not driving.
|
||||
if(getSpeed()==0) return 0.0f;
|
||||
const float dx = point[0] - getXYZ().getX();
|
||||
const float dy = point[1] - getXYZ().getY();
|
||||
const float dx = point.getX() - getXYZ().getX();
|
||||
const float dy = point.getY() - getXYZ().getY();
|
||||
/** Angle from the kart position to the point in world coordinates. */
|
||||
float theta = -atan2(dx, dy);
|
||||
|
||||
@@ -899,12 +914,9 @@ void DefaultRobot::checkCrashes( const int STEPS, const Vec3& pos )
|
||||
* the two edges of the track is closest to the next curve after wards,
|
||||
* and return the position of that edge.
|
||||
*/
|
||||
void DefaultRobot::findNonCrashingPoint( Vec2 result )
|
||||
{
|
||||
const unsigned int DRIVELINE_SIZE = (unsigned int)m_track->m_driveline.size();
|
||||
|
||||
unsigned int sector = (unsigned int)m_track_sector + 1 < DRIVELINE_SIZE
|
||||
? m_track_sector + 1 : 0;
|
||||
void DefaultRobot::findNonCrashingPoint(Vec3 *result)
|
||||
{
|
||||
unsigned int sector = m_next_quad_index[m_track_sector];
|
||||
int target_sector;
|
||||
|
||||
Vec3 direction;
|
||||
@@ -917,10 +929,10 @@ void DefaultRobot::findNonCrashingPoint( Vec2 result )
|
||||
{
|
||||
//target_sector is the sector at the longest distance that we can drive
|
||||
//to without crashing with the track.
|
||||
target_sector = sector + 1 < DRIVELINE_SIZE ? sector + 1 : 0;
|
||||
target_sector = m_next_quad_index[sector];
|
||||
|
||||
//direction is a vector from our kart to the sectors we are testing
|
||||
direction = m_track->m_driveline[target_sector] - getXYZ();
|
||||
direction = m_quad_graph->getCenterOfQuad(target_sector) - getXYZ();
|
||||
|
||||
float len=direction.length_2d();
|
||||
steps = int( len / m_kart_length );
|
||||
@@ -946,8 +958,7 @@ void DefaultRobot::findNonCrashingPoint( Vec2 result )
|
||||
//If we are outside, the previous sector is what we are looking for
|
||||
if ( distance + m_kart_width * 0.5f > m_track->getWidth()[sector] )
|
||||
{
|
||||
result = m_track->m_driveline[sector];
|
||||
//sgCopyVec2( result, m_track->m_driveline[sector] );
|
||||
*result = m_quad_graph->getCenterOfQuad(sector);
|
||||
|
||||
#ifdef SHOW_NON_CRASHING_POINT
|
||||
ssgaSphere *sphere = new ssgaSphere;
|
||||
@@ -1080,83 +1091,6 @@ void DefaultRobot::setSteering(float angle, float dt)
|
||||
}
|
||||
} // setSteering
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Finds the approximate radius of a track's curve. It needs two arguments,
|
||||
* the number of the drivepoint that marks the beginning of the curve, and
|
||||
* the number of the drivepoint that marks the ending of the curve.
|
||||
*
|
||||
* Based on that you can construct any circle out of 3 points in it, we use
|
||||
* the two arguments to use the drivelines as the first and last point; the
|
||||
* middle sector is averaged.
|
||||
*/
|
||||
float DefaultRobot::getApproxRadius(const int START, const int END) const
|
||||
{
|
||||
const int MIDDLE = (START + END) / 2;
|
||||
|
||||
//If the START and END sectors are very close, their average will be one
|
||||
//of them, and using twice the same point just generates a huge radius
|
||||
//(too big to be of any use) but it also can generate a division by zero,
|
||||
//so here is some special handling for that case.
|
||||
if (MIDDLE == START || MIDDLE == END ) return 99999.0f;
|
||||
|
||||
float X1, Y1, X2, Y2, X3, Y3;
|
||||
|
||||
//The next line is just to avoid compiler warnings.
|
||||
X1 = X2 = X3 = Y1 = Y2 = Y3 = 0.0;
|
||||
|
||||
|
||||
if(m_inner_curve == -1)
|
||||
{
|
||||
X1 = m_track->m_left_driveline[START][0];
|
||||
Y1 = m_track->m_left_driveline[START][1];
|
||||
|
||||
X2 = m_track->m_left_driveline[MIDDLE][0];
|
||||
Y2 = m_track->m_left_driveline[MIDDLE][1];
|
||||
|
||||
X3 = m_track->m_left_driveline[END][0];
|
||||
Y3 = m_track->m_left_driveline[END][1];
|
||||
}
|
||||
else if (m_inner_curve == 0)
|
||||
{
|
||||
X1 = m_track->m_driveline[START][0];
|
||||
Y1 = m_track->m_driveline[START][1];
|
||||
|
||||
X2 = m_track->m_driveline[MIDDLE][0];
|
||||
Y2 = m_track->m_driveline[MIDDLE][1];
|
||||
|
||||
X3 = m_track->m_driveline[END][0];
|
||||
Y3 = m_track->m_driveline[END][1];
|
||||
}
|
||||
else if (m_inner_curve == 1)
|
||||
{
|
||||
X1 = m_track->m_right_driveline[START][0];
|
||||
Y1 = m_track->m_right_driveline[START][1];
|
||||
|
||||
X2 = m_track->m_right_driveline[MIDDLE][0];
|
||||
Y2 = m_track->m_right_driveline[MIDDLE][1];
|
||||
|
||||
X3 = m_track->m_right_driveline[END][0];
|
||||
Y3 = m_track->m_right_driveline[END][1];
|
||||
}
|
||||
|
||||
const float A = X2 - X1;
|
||||
const float B = Y2 - Y1;
|
||||
const float C = X3 - X1;
|
||||
const float D = Y3 - Y1;
|
||||
|
||||
const float E = A * ( X1 + X2) + B * (Y1 + Y2);
|
||||
const float F = C * ( X1 + X3) + D * (Y1 + Y3);
|
||||
|
||||
const float G = 2.0f * ( A*( Y3-Y2 ) - B*( X3 - X2 ) );
|
||||
|
||||
const float pX = ( D*E - B*F) / G;
|
||||
const float pY = ( A*F - C*E) / G;
|
||||
|
||||
const float radius = sqrt( ( X1 - pX) * ( X1 - pX) + (Y1 - pY) * (Y1 - pY) );
|
||||
|
||||
return radius;
|
||||
} // getApproxRadius
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/**FindCurve() gathers info about the closest sectors ahead: the curve
|
||||
* angle, the direction of the next turn, and the optimal speed at which the
|
||||
@@ -1166,23 +1100,12 @@ float DefaultRobot::getApproxRadius(const int START, const int END) const
|
||||
*/
|
||||
void DefaultRobot::findCurve()
|
||||
{
|
||||
const int DRIVELINE_SIZE = (unsigned int)m_track->m_driveline.size();
|
||||
float total_dist = 0.0f;
|
||||
int next_hint = m_track_sector;
|
||||
int i;
|
||||
|
||||
for(i = m_track_sector; total_dist < getVelocityLC().getY(); i = next_hint)
|
||||
for(i = m_track_sector; total_dist < getVelocityLC().getY();
|
||||
i = m_next_quad_index[i])
|
||||
{
|
||||
next_hint = i + 1 < DRIVELINE_SIZE ? i + 1 : 0;
|
||||
// Note that m_driveline[...].getZ() might be undefined and trigger
|
||||
// an exception when used. So we can't just write
|
||||
// (m_driveline[i]-m_driveline[next_hint]).length_2d()
|
||||
Vec3 v;
|
||||
v.setX(m_track->m_driveline[i].getX() - m_track->m_driveline[next_hint].getX());
|
||||
v.setY(m_track->m_driveline[i].getY() - m_track->m_driveline[next_hint].getY());
|
||||
// length_2d only uses the X and Y component.
|
||||
// FIXME: the values of v.length could be pre-computed and saved
|
||||
total_dist += v.length_2d();
|
||||
total_dist += m_quad_graph->getDistanceToNext(i, m_successor_index[i]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -23,11 +23,11 @@
|
||||
#include "utils/vec3.hpp"
|
||||
|
||||
/* third coord won't be used */
|
||||
typedef Vec3 Vec2;
|
||||
|
||||
class Track;
|
||||
class LinearWorld;
|
||||
class TrackInfo;
|
||||
class QuadGraph;
|
||||
|
||||
class DefaultRobot : public AutoKart
|
||||
{
|
||||
@@ -106,7 +106,7 @@ private:
|
||||
/** Time an item has been collected and not used. */
|
||||
float m_time_since_last_shot;
|
||||
int m_future_sector;
|
||||
Vec2 m_future_location;
|
||||
Vec3 m_future_location;
|
||||
|
||||
float m_time_till_start; //Used to simulate a delay at the start of the
|
||||
//race, since human players don't accelerate
|
||||
@@ -124,8 +124,16 @@ private:
|
||||
LinearWorld *m_world;
|
||||
/** Cache kart_info.m_track_sector. */
|
||||
int m_track_sector;
|
||||
|
||||
/** The graph of qudas of this track. */
|
||||
const QuadGraph *m_quad_graph;
|
||||
|
||||
/** Which of the successors of a node was selected by the AI. */
|
||||
std::vector<int> m_successor_index;
|
||||
/** For each node in the graph this list contained the chosen next node.
|
||||
* For normal lap track without branches we always have
|
||||
* m_next_quad_index[i] = (i+1) % size;
|
||||
* but if a branch is possible, the AI will select one option here. */
|
||||
std::vector<int> m_next_quad_index;
|
||||
float m_time_since_stuck;
|
||||
|
||||
int m_start_kart_crash_direction; //-1 = left, 1 = right, 0 = no crash.
|
||||
@@ -167,15 +175,14 @@ private:
|
||||
|
||||
/*Lower level functions not called directly from update()*/
|
||||
float steerToAngle(const size_t SECTOR, const float ANGLE);
|
||||
float steerToPoint(const Vec2 point, float dt);
|
||||
float steerToPoint(const Vec3 &point, float dt);
|
||||
|
||||
void checkCrashes(const int STEPS, const Vec2& pos);
|
||||
void findNonCrashingPoint(Vec2 result);
|
||||
void checkCrashes(const int STEPS, const Vec3& pos);
|
||||
void findNonCrashingPoint(Vec3 *result);
|
||||
|
||||
float normalizeAngle(float angle);
|
||||
int calcSteps();
|
||||
void setSteering(float angle, float dt);
|
||||
float getApproxRadius(const int START, const int END) const;
|
||||
void findCurve();
|
||||
|
||||
public:
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#include "robots/track_info.hpp"
|
||||
|
||||
#include "tracks/quad_graph.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
#include "utils/constants.hpp"
|
||||
|
||||
@@ -36,7 +37,7 @@ void TrackInfo::setupSteerInfo()
|
||||
// First find the beginning of a new section, i.e. a place where the track
|
||||
// direction changes from either straight to curve or the other way round.
|
||||
int i = 0;
|
||||
int num_drivelines = m_track->m_driveline.size();
|
||||
int num_drivelines = m_track->getQuadGraph().getNumNodes();
|
||||
// not ready yet float current_angle = m_track->m_angle[i];
|
||||
while(i<num_drivelines)
|
||||
{
|
||||
|
||||
@@ -104,8 +104,6 @@ void STKConfig::load(const std::string &filename)
|
||||
CHECK_NEG(m_zipper_time, "zipper-time" );
|
||||
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_final_camera_time, "final-camera-time" );
|
||||
CHECK_NEG(m_explosion_impulse, "explosion-impulse" );
|
||||
CHECK_NEG(m_explosion_impulse_objects, "explosion-impulse-objects" );
|
||||
@@ -137,11 +135,9 @@ void STKConfig::init_defaults()
|
||||
m_anvil_time = m_zipper_time =
|
||||
m_zipper_force = m_zipper_speed_gain =
|
||||
m_explosion_impulse = m_explosion_impulse_objects =
|
||||
m_shortcut_length = m_music_credit_time =
|
||||
m_music_credit_time = m_slowdown_factor =
|
||||
m_delay_finish_time = m_skid_fadeout_time =
|
||||
m_slowdown_factor = m_offroad_tolerance =
|
||||
m_final_camera_time = m_near_ground =
|
||||
UNDEFINED;
|
||||
m_final_camera_time = m_near_ground = UNDEFINED;
|
||||
m_max_karts = -100;
|
||||
m_grid_order = -100;
|
||||
m_max_history = -100;
|
||||
@@ -184,8 +180,6 @@ 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("offroad-tolerance", m_offroad_tolerance );
|
||||
lisp->get("final-camera-time", m_final_camera_time );
|
||||
lisp->get("anvil-speed-factor", m_anvil_speed_factor );
|
||||
lisp->get("parachute-friction", m_parachute_friction );
|
||||
|
||||
@@ -53,11 +53,6 @@ public:
|
||||
float m_zipper_force; /**<Additional force added to the
|
||||
acceleration. */
|
||||
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_final_camera_time; /**<Time for the movement of the final
|
||||
* camera. */
|
||||
float m_explosion_impulse; /**<Impulse affecting each non-hit kart.*/
|
||||
|
||||
@@ -25,22 +25,25 @@
|
||||
|
||||
/** Constructor, loads the graph information for a given set of quads
|
||||
* from a graph file.
|
||||
* \param filename Name of the file to load.
|
||||
* \param quad_set The set of quads to which the graph applies.
|
||||
* \param quad_file_name Name of the file of all quads
|
||||
* \param graph_file_name Name of the file describing the actual graph
|
||||
*/
|
||||
QuadGraph::QuadGraph(const std::string &filename, QuadSet* quad_set)
|
||||
QuadGraph::QuadGraph(const std::string &quad_file_name,
|
||||
const std::string graph_file_name)
|
||||
{
|
||||
m_all_quads = new QuadSet(quad_file_name);
|
||||
// First create all nodes
|
||||
for(unsigned int i=0; i<quad_set->getSize(); i++) {
|
||||
m_all_nodes.push_back(new GraphNode);
|
||||
for(unsigned int i=0; i<m_all_quads->getSize(); i++) {
|
||||
m_all_nodes.push_back(new GraphNode(i));
|
||||
}
|
||||
load(filename);
|
||||
load(graph_file_name);
|
||||
} // QuadGraph
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
/** Destructor, removes all nodes of the graph. */
|
||||
QuadGraph::~QuadGraph()
|
||||
{
|
||||
delete m_all_quads;
|
||||
for(unsigned int i=0; i<m_all_nodes.size(); i++) {
|
||||
delete m_all_nodes[i];
|
||||
}
|
||||
@@ -73,7 +76,7 @@ void QuadGraph::load(const std::string &filename)
|
||||
node->get("from", &from);
|
||||
node->get("to", &to);
|
||||
assert(from>=0 && from <(int)m_all_nodes.size());
|
||||
m_all_nodes[from]->addSuccessor(to);
|
||||
m_all_nodes[from]->addSuccessor(to, *m_all_quads);
|
||||
} // from
|
||||
delete xml;
|
||||
|
||||
@@ -88,7 +91,8 @@ void QuadGraph::setDefaultSuccessors()
|
||||
{
|
||||
for(unsigned int i=0; i<m_all_nodes.size(); i++) {
|
||||
if(m_all_nodes[i]->getNumberOfSuccessors()==0) {
|
||||
m_all_nodes[i]->addSuccessor( i+1>=m_all_nodes.size() ? 0 : i+1);
|
||||
m_all_nodes[i]->addSuccessor(i+1>=m_all_nodes.size() ? 0 : i+1,
|
||||
*m_all_quads);
|
||||
} // if size==0
|
||||
} // for i<m_allNodes.size()
|
||||
} // setDefaultSuccessors
|
||||
@@ -98,10 +102,23 @@ void QuadGraph::setDefaultSuccessors()
|
||||
* \param node_number The number of the node.
|
||||
* \param succ A vector of ints to which the successors are added.
|
||||
*/
|
||||
void QuadGraph::getSuccessors(int node_number, std::vector<int>& succ) const {
|
||||
void QuadGraph::getSuccessors(int node_number, std::vector<unsigned int>& succ) const {
|
||||
const GraphNode *v=m_all_nodes[node_number];
|
||||
for(unsigned int i=0; i<v->getNumberOfSuccessors(); i++) {
|
||||
succ.push_back((*v)[i]);
|
||||
}
|
||||
} // getSuccessors
|
||||
|
||||
// ============================================================================
|
||||
/** Adds a successor to a node. This function will also pre-compute certain
|
||||
* values (like distance from this node to the successor, angle (in world)
|
||||
* between this node and the successor.
|
||||
* \param to The index of the successor.
|
||||
*/
|
||||
void QuadGraph::GraphNode::addSuccessor(int to, const QuadSet &quad_set)
|
||||
{
|
||||
m_vertices.push_back(to);
|
||||
Vec3 diff = quad_set.getCenterOfQuad(to)
|
||||
- quad_set.getCenterOfQuad(m_index);
|
||||
m_distance_to_next.push_back(diff.length());
|
||||
} // addSuccessor
|
||||
@@ -23,7 +23,7 @@
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
class QuadSet;
|
||||
#include "tracks/quad_set.hpp"
|
||||
|
||||
/** This class stores a graph of quads. */
|
||||
class QuadGraph {
|
||||
@@ -31,27 +31,54 @@ class QuadGraph {
|
||||
* edges. */
|
||||
class GraphNode
|
||||
{
|
||||
/** Index of this node in m_all_quads. */
|
||||
int m_index;
|
||||
/** The list of successors. */
|
||||
std::vector<int> m_vertices;
|
||||
std::vector<int> m_vertices;
|
||||
/** The distance to each of the successors. */
|
||||
std::vector<float> m_distance_to_next;
|
||||
public:
|
||||
/** Adds a successor to a node. */
|
||||
void addSuccessor (int to) {m_vertices.push_back(to); }
|
||||
/** Constructor, stores the index.
|
||||
* \param index Index of this node in m_all_quads. */
|
||||
GraphNode(int index) { m_index = index; }
|
||||
void addSuccessor (int to, const QuadSet &quad_set);
|
||||
/** Returns the i-th successor. */
|
||||
unsigned int operator[] (int i) const {return m_vertices[i]; }
|
||||
unsigned int operator[] (int i) const {return m_vertices[i]; }
|
||||
/** Returns the number of successors. */
|
||||
unsigned int getNumberOfSuccessors() const
|
||||
{ return (unsigned int)m_vertices.size(); }
|
||||
{ return (unsigned int)m_vertices.size(); }
|
||||
/** Returns the distance to the j-th. successor. */
|
||||
float getDistanceToSuccessor(int j) const
|
||||
{ return m_distance_to_next[j]; }
|
||||
};
|
||||
|
||||
// ========================================================================
|
||||
protected:
|
||||
/** The actual graph data structure. */
|
||||
std::vector<GraphNode*> m_all_nodes;
|
||||
QuadSet *m_all_quads;
|
||||
void setDefaultSuccessors();
|
||||
void load (const std::string &filename);
|
||||
|
||||
public:
|
||||
QuadGraph (const std::string &filename, QuadSet *quad_set);
|
||||
~QuadGraph ();
|
||||
void getSuccessors(int quadNumber, std::vector<int>& succ) const;
|
||||
QuadGraph (const std::string &quad_file_name,
|
||||
const std::string graph_file_name);
|
||||
~QuadGraph ();
|
||||
void getSuccessors(int quadNumber,
|
||||
std::vector<unsigned int>& succ) const;
|
||||
|
||||
/** Returns the number of nodes in the graph. */
|
||||
unsigned int getNumNodes() const { return m_all_nodes.size(); }
|
||||
/** Returns the quad set for this graph. */
|
||||
const QuadSet* getQuads() const { return m_all_quads; }
|
||||
/** Returns the center of a quad.
|
||||
* \param n Index of the quad. */
|
||||
const Vec3& getCenterOfQuad(int n) const
|
||||
{ return m_all_quads->getCenterOfQuad(n); }
|
||||
/** Return the distance to the j-th successor of node n. */
|
||||
float getDistanceToNext(int n, int j) const
|
||||
{ return m_all_nodes[n]->getDistanceToSuccessor(j);}
|
||||
|
||||
}; // QuadGraph
|
||||
|
||||
#endif
|
||||
|
||||
@@ -37,7 +37,7 @@ private:
|
||||
computations at runtime. */
|
||||
Vec3 m_center;
|
||||
/** Constructor, takes 4 points. */
|
||||
Quad(btVector3 p0, btVector3 p1, btVector3 p2, btVector3 p3)
|
||||
Quad(const Vec3 &p0, const Vec3 &p1, const Vec3 &p2, const Vec3 &p3)
|
||||
{
|
||||
m_p[0]=p0; m_p[1]=p1; m_p[2]=p2; m_p[3]=p3;
|
||||
m_center = 0.25f*(p0+p1+p2+p3);
|
||||
@@ -48,7 +48,7 @@ private:
|
||||
/** Returns the i-th. point of a quad. */
|
||||
const btVector3& operator[](int i) const {return m_p[i]; }
|
||||
/** Returns the center of a quad. */
|
||||
const btVector3& getCenter () const {return m_center; }
|
||||
const Vec3& getCenter () const {return m_center; }
|
||||
}; // class Quad
|
||||
// =======================================================================
|
||||
/** The 2d bounding box, used for hashing. */
|
||||
@@ -78,7 +78,7 @@ public:
|
||||
/** Returns the number of quads. */
|
||||
unsigned int getSize() const {return (unsigned int)m_allQuads.size(); }
|
||||
/** Returns the center of quad n. */
|
||||
const btVector3& getCenterOfQuad(int n) const
|
||||
const Vec3& getCenterOfQuad(int n) const
|
||||
{return m_allQuads[n]->getCenter(); }
|
||||
}; // QuadSet
|
||||
#endif
|
||||
|
||||
@@ -74,7 +74,6 @@ Track::Track( std::string filename_, float w, float h, bool stretch )
|
||||
m_all_meshes.clear();
|
||||
m_has_final_camera = false;
|
||||
m_is_arena = false;
|
||||
m_quads = NULL;
|
||||
m_quad_graph = NULL;
|
||||
loadTrack(m_filename);
|
||||
loadDriveline();
|
||||
@@ -85,7 +84,6 @@ Track::Track( std::string filename_, float w, float h, bool stretch )
|
||||
/** Destructor, removes quad data structures etc. */
|
||||
Track::~Track()
|
||||
{
|
||||
if(m_quads) delete m_quads;
|
||||
if(m_quad_graph) delete m_quad_graph;
|
||||
} // ~Track
|
||||
|
||||
@@ -169,34 +167,18 @@ int Track::pointInQuad
|
||||
* \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,
|
||||
bool with_tolerance )const
|
||||
void Track::findRoadSector(const Vec3& XYZ, int *sector)const
|
||||
{
|
||||
if(*sector!=UNKNOWN_SECTOR)
|
||||
{
|
||||
int next = (unsigned)(*sector) + 1 < m_left_driveline.size() ? *sector + 1 : 0;
|
||||
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;
|
||||
}
|
||||
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
|
||||
@@ -210,12 +192,7 @@ void Track::findRoadSector(const Vec3& XYZ, int *sector,
|
||||
for( size_t i = 0; i < DRIVELINE_SIZE ; ++i )
|
||||
{
|
||||
next = (unsigned int)i + 1 < DRIVELINE_SIZE ? (int)i + 1 : 0;
|
||||
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],
|
||||
triangle = pointInQuad(m_left_driveline[i], m_right_driveline[i],
|
||||
m_right_driveline[next], m_left_driveline[next],
|
||||
XYZ );
|
||||
|
||||
@@ -501,33 +478,6 @@ btTransform Track::getStartTransform(unsigned int pos) const
|
||||
return start;
|
||||
} // getStartTransform
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Determines if a kart moving from sector OLDSEC to sector NEWSEC
|
||||
* would be taking a shortcut, i.e. if the distance is larger
|
||||
* than a certain delta
|
||||
*/
|
||||
bool Track::isShortcut(const int OLDSEC, const int NEWSEC) const
|
||||
{
|
||||
// If the kart was off the road, don't do any shortcuts
|
||||
if(OLDSEC==UNKNOWN_SECTOR || NEWSEC==UNKNOWN_SECTOR) return false;
|
||||
int next_sector = OLDSEC==(int)m_driveline.size()-1 ? 0 : OLDSEC+1;
|
||||
if(next_sector==NEWSEC)
|
||||
return false;
|
||||
|
||||
int distance_sectors = (int)(m_distance_from_start[std::max(NEWSEC, OLDSEC)] -
|
||||
m_distance_from_start[std::min(NEWSEC, OLDSEC)] );
|
||||
|
||||
// Handle 'warp around'
|
||||
const int track_length = (int)m_distance_from_start[m_driveline.size()-1];
|
||||
if( distance_sectors < 0 ) distance_sectors += track_length;
|
||||
//else if( distance_sectors > track_length*3.0f/4.0f) distance_sectors -= track_length;
|
||||
|
||||
if(std::max(NEWSEC, OLDSEC) > (int)RaceManager::getTrack()->m_distance_from_start.size()-6 &&
|
||||
std::min(NEWSEC, OLDSEC) < 6) distance_sectors -= track_length; // crossed start line
|
||||
|
||||
return (distance_sectors > stk_config->m_shortcut_length);
|
||||
} // isShortcut
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void Track::addDebugToScene(int type) const
|
||||
{
|
||||
@@ -559,16 +509,14 @@ void Track::addDebugToScene(int type) const
|
||||
} // for i
|
||||
*/
|
||||
} /// type ==1
|
||||
// 2: drivelines, 4: driveline with tolerance
|
||||
if(type & 6)
|
||||
// 2: drivelines
|
||||
if(type & 2)
|
||||
{
|
||||
/*
|
||||
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;
|
||||
const std::vector<Vec3> &left = m_left_driveline;
|
||||
const std::vector<Vec3> &right = m_right_driveline;
|
||||
for(unsigned int i = 0; i < m_driveline.size(); i++)
|
||||
{
|
||||
int ip1 = i==m_driveline.size()-1 ? 0 : i+1;
|
||||
@@ -1002,9 +950,8 @@ void Track::startMusic() const
|
||||
//-----------------------------------------------------------------------------
|
||||
void Track::loadDriveline()
|
||||
{
|
||||
m_quads = new QuadSet (file_manager->getTrackFile(m_ident+".quads"));
|
||||
m_quad_graph = new QuadGraph(file_manager->getTrackFile(m_ident+".graph"),
|
||||
m_quads);
|
||||
m_quad_graph = new QuadGraph(file_manager->getTrackFile(m_ident+".quads"),
|
||||
file_manager->getTrackFile(m_ident+".graph"));
|
||||
readDrivelineFromFile(m_left_driveline, ".drvl");
|
||||
|
||||
const unsigned int DRIVELINE_SIZE = (unsigned int)m_left_driveline.size();
|
||||
@@ -1017,8 +964,6 @@ void 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);
|
||||
@@ -1029,13 +974,6 @@ void 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)
|
||||
|
||||
@@ -42,7 +42,6 @@ class TriangleMesh;
|
||||
class MovingTexture;
|
||||
class XMLNode;
|
||||
class PhysicalObject;
|
||||
class QuadSet;
|
||||
class QuadGraph;
|
||||
|
||||
class Track
|
||||
@@ -70,8 +69,6 @@ private:
|
||||
int m_version;
|
||||
bool loadMainTrack(const XMLNode &node);
|
||||
void createWater(const XMLNode &node);
|
||||
/** The set of all quads for this track. */
|
||||
QuadSet *m_quads;
|
||||
/** The graph used to connect the quads. */
|
||||
QuadGraph *m_quad_graph;
|
||||
/** The type of sky to be used for the track. */
|
||||
@@ -138,11 +135,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?
|
||||
private:
|
||||
std::vector<Vec3> m_driveline;
|
||||
public:
|
||||
/** 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<float> m_distance_from_start;
|
||||
std::vector<float> m_path_width;
|
||||
std::vector<float> m_angle;
|
||||
@@ -179,8 +176,7 @@ public:
|
||||
void drawScaled2D (float x, float y, float w,
|
||||
float h ) const;
|
||||
|
||||
void findRoadSector (const Vec3& XYZ, int *sector,
|
||||
bool with_tolerance=false) const;
|
||||
void findRoadSector (const Vec3& XYZ, int *sector) const;
|
||||
int findOutOfRoadSector(const Vec3& XYZ,
|
||||
const RoadSide SIDE,
|
||||
const int CURR_SECTOR
|
||||
@@ -190,7 +186,6 @@ public:
|
||||
const int SECTOR ) const;
|
||||
const Vec3& trackToSpatial (const int SECTOR) const;
|
||||
void loadTrackModel ();
|
||||
bool isShortcut (const int OLDSEC, const int NEWSEC) const;
|
||||
void addMusic (MusicInformation* mi)
|
||||
{m_music.push_back(mi); }
|
||||
float getGravity () const {return m_gravity; }
|
||||
@@ -228,6 +223,9 @@ public:
|
||||
void createPhysicsModel();
|
||||
void update(float dt);
|
||||
void handleExplosion(const Vec3 &pos, const PhysicalObject *mp) const;
|
||||
|
||||
/** Returns the graph of quads, mainly for the AI. */
|
||||
const QuadGraph& getQuadGraph() const { return *m_quad_graph; }
|
||||
/*
|
||||
void glVtx (sgVec2 v, float x_offset, float y_offset) const
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user