Moved the path selection and track quad determination code from
default_ai_controller to ai_base_controller. This way all controllers (esp end controller) benefit from the fix in quad determination without having to apply the same patch in several files. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@6489 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
parent
27477ea270
commit
8d40c65190
@ -34,11 +34,93 @@ AIBaseController::AIBaseController(Kart *kart,
|
|||||||
m_kart = kart;
|
m_kart = kart;
|
||||||
m_kart_length = m_kart->getKartModel()->getLength();
|
m_kart_length = m_kart->getKartModel()->getLength();
|
||||||
m_kart_width = m_kart->getKartModel()->getWidth();
|
m_kart_width = m_kart->getKartModel()->getWidth();
|
||||||
|
|
||||||
|
if(race_manager->getMinorMode()!=RaceManager::MINOR_MODE_3_STRIKES)
|
||||||
|
{
|
||||||
m_world = dynamic_cast<LinearWorld*>(World::getWorld());
|
m_world = dynamic_cast<LinearWorld*>(World::getWorld());
|
||||||
m_track = m_world->getTrack();
|
m_track = m_world->getTrack();
|
||||||
m_quad_graph = &m_track->getQuadGraph();
|
m_quad_graph = &m_track->getQuadGraph();
|
||||||
|
|
||||||
|
m_next_node_index.reserve(m_quad_graph->getNumNodes());
|
||||||
|
m_successor_index.reserve(m_quad_graph->getNumNodes());
|
||||||
|
std::vector<unsigned int> next;
|
||||||
|
|
||||||
|
for(unsigned int i=0; i<m_quad_graph->getNumNodes(); i++)
|
||||||
|
{
|
||||||
|
next.clear();
|
||||||
|
m_quad_graph->getSuccessors(i, next);
|
||||||
|
// For now pick one part on random, which is not adjusted during the
|
||||||
|
// race. Long term statistics might be gathered to determine the
|
||||||
|
// best way, potentially depending on race position etc.
|
||||||
|
int indx = rand() % next.size();
|
||||||
|
m_successor_index.push_back(indx);
|
||||||
|
m_next_node_index.push_back(next[indx]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const unsigned int look_ahead=10;
|
||||||
|
// Now compute for each node in the graph the list of the next 'look_ahead'
|
||||||
|
// graph nodes. This is the list of node that is tested in checkCrashes.
|
||||||
|
// If the look_ahead is too big, the AI can skip loops (see
|
||||||
|
// QuadGraph::findRoadSector for details), if it's too short the AI won't
|
||||||
|
// find too good a driveline. Note that in general this list should
|
||||||
|
// be computed recursively, but since the AI for now is using only
|
||||||
|
// (randomly picked) path this is fine
|
||||||
|
m_all_look_aheads.reserve(m_quad_graph->getNumNodes());
|
||||||
|
for(unsigned int i=0; i<m_quad_graph->getNumNodes(); i++)
|
||||||
|
{
|
||||||
|
std::vector<int> l;
|
||||||
|
int current = i;
|
||||||
|
for(unsigned int j=0; j<look_ahead; j++)
|
||||||
|
{
|
||||||
|
l.push_back(m_next_node_index[current]);
|
||||||
|
current = m_next_node_index[current];
|
||||||
|
} // for j<look_ahead
|
||||||
|
m_all_look_aheads.push_back(l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Those variables are not defined in a battle mode (m_world is
|
||||||
|
// a linear world, since it assumes the existance of drivelines)
|
||||||
|
m_world = NULL;
|
||||||
|
m_track = NULL;
|
||||||
|
m_quad_graph = NULL;
|
||||||
|
m_next_node_index.clear();
|
||||||
|
m_all_look_aheads.clear();
|
||||||
|
m_successor_index.clear();
|
||||||
|
} // if battle mode
|
||||||
|
|
||||||
} // AIBaseController
|
} // AIBaseController
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void AIBaseController::update(float dt)
|
||||||
|
{
|
||||||
|
Controller::update(dt);
|
||||||
|
|
||||||
|
if(m_quad_graph)
|
||||||
|
{
|
||||||
|
// Update the current node:
|
||||||
|
int old_node = m_track_node;
|
||||||
|
if(m_track_node!=QuadGraph::UNKNOWN_SECTOR)
|
||||||
|
{
|
||||||
|
m_quad_graph->findRoadSector(m_kart->getXYZ(), &m_track_node,
|
||||||
|
&m_all_look_aheads[m_track_node]);
|
||||||
|
}
|
||||||
|
// If we can't find a proper place on the track, to a broader search
|
||||||
|
// on off-track locations.
|
||||||
|
if(m_track_node==QuadGraph::UNKNOWN_SECTOR)
|
||||||
|
{
|
||||||
|
m_track_node = m_quad_graph->findOutOfRoadSector(m_kart->getXYZ());
|
||||||
|
}
|
||||||
|
// IF the AI is off track (or on a branch of the track it did not
|
||||||
|
// select to be on), keep the old position.
|
||||||
|
if(m_track_node==QuadGraph::UNKNOWN_SECTOR ||
|
||||||
|
m_next_node_index[m_track_node]==-1)
|
||||||
|
m_track_node = old_node;
|
||||||
|
}
|
||||||
|
} // update
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
/** Returns the next sector of the given sector index. This is used
|
/** Returns the next sector of the given sector index. This is used
|
||||||
* for branches in the quad graph to select which way the AI kart should
|
* for branches in the quad graph to select which way the AI kart should
|
||||||
|
@ -55,6 +55,25 @@ protected:
|
|||||||
/** The graph of qudas of this track. */
|
/** The graph of qudas of this track. */
|
||||||
const QuadGraph *m_quad_graph;
|
const QuadGraph *m_quad_graph;
|
||||||
|
|
||||||
|
/** The current node the kart is on. This can be different from the value
|
||||||
|
* in LinearWorld, since it takes the chosen path of the AI into account
|
||||||
|
* (e.g. the closest point in LinearWorld might be on a branch not
|
||||||
|
* chosen by the AI). */
|
||||||
|
int m_track_node;
|
||||||
|
|
||||||
|
/** 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 contains the chosen next node.
|
||||||
|
* For normal lap track without branches we always have
|
||||||
|
* m_next_node_index[i] = (i+1) % size;
|
||||||
|
* but if a branch is possible, the AI will select one option here.
|
||||||
|
* If the node is not used, m_next_node_index will be -1. */
|
||||||
|
std::vector<int> m_next_node_index;
|
||||||
|
/** For each graph node this list contains a list of the next X
|
||||||
|
* graph nodes. */
|
||||||
|
std::vector<std::vector<int> > m_all_look_aheads;
|
||||||
|
|
||||||
|
virtual void update (float delta) ;
|
||||||
float steerToAngle (const unsigned int sector, const float angle);
|
float steerToAngle (const unsigned int sector, const float angle);
|
||||||
float steerToPoint (const Vec3 &point);
|
float steerToPoint (const Vec3 &point);
|
||||||
float normalizeAngle(float angle);
|
float normalizeAngle(float angle);
|
||||||
|
@ -48,43 +48,6 @@
|
|||||||
|
|
||||||
DefaultAIController::DefaultAIController(Kart *kart) : AIBaseController(kart)
|
DefaultAIController::DefaultAIController(Kart *kart) : AIBaseController(kart)
|
||||||
{
|
{
|
||||||
m_next_node_index.reserve(m_quad_graph->getNumNodes());
|
|
||||||
m_successor_index.reserve(m_quad_graph->getNumNodes());
|
|
||||||
std::vector<unsigned int> next;
|
|
||||||
|
|
||||||
for(unsigned int i=0; i<m_quad_graph->getNumNodes(); i++)
|
|
||||||
{
|
|
||||||
next.clear();
|
|
||||||
m_quad_graph->getSuccessors(i, next);
|
|
||||||
// For now pick one part on random, which is not adjusted during the
|
|
||||||
// race. Long term statistics might be gathered to determine the
|
|
||||||
// best way, potentially depending on race position etc.
|
|
||||||
int indx = rand() % next.size();
|
|
||||||
m_successor_index.push_back(indx);
|
|
||||||
m_next_node_index.push_back(next[indx]);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const unsigned int look_ahead=10;
|
|
||||||
// Now compute for each node in the graph the list of the next 'look_ahead'
|
|
||||||
// graph nodes. This is the list of node that is tested in checkCrashes.
|
|
||||||
// If the look_ahead is too big, the AI can skip loops (see
|
|
||||||
// QuadGraph::findRoadSector for details), if it's too short the AI won't
|
|
||||||
// find too good a driveline. Note that in general this list should
|
|
||||||
// be computed recursively, but since the AI for now is using only
|
|
||||||
// (randomly picked) path this is fine
|
|
||||||
m_all_look_aheads.reserve(m_quad_graph->getNumNodes());
|
|
||||||
for(unsigned int i=0; i<m_quad_graph->getNumNodes(); i++)
|
|
||||||
{
|
|
||||||
std::vector<int> l;
|
|
||||||
int current = i;
|
|
||||||
for(unsigned int j=0; j<look_ahead; j++)
|
|
||||||
{
|
|
||||||
l.push_back(m_next_node_index[current]);
|
|
||||||
current = m_next_node_index[current];
|
|
||||||
} // for j<look_ahead
|
|
||||||
m_all_look_aheads.push_back(l);
|
|
||||||
}
|
|
||||||
// Reset must be called after m_quad_graph etc. is set up
|
// Reset must be called after m_quad_graph etc. is set up
|
||||||
reset();
|
reset();
|
||||||
|
|
||||||
@ -166,7 +129,7 @@ void DefaultAIController::reset()
|
|||||||
m_kart_behind = NULL;
|
m_kart_behind = NULL;
|
||||||
m_distance_behind = 0.0f;
|
m_distance_behind = 0.0f;
|
||||||
|
|
||||||
Controller::reset();
|
AIBaseController::reset();
|
||||||
m_track_node = QuadGraph::UNKNOWN_SECTOR;
|
m_track_node = QuadGraph::UNKNOWN_SECTOR;
|
||||||
m_quad_graph->findRoadSector(m_kart->getXYZ(), &m_track_node);
|
m_quad_graph->findRoadSector(m_kart->getXYZ(), &m_track_node);
|
||||||
if(m_track_node==QuadGraph::UNKNOWN_SECTOR)
|
if(m_track_node==QuadGraph::UNKNOWN_SECTOR)
|
||||||
@ -214,36 +177,17 @@ void DefaultAIController::update(float dt)
|
|||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Update the current node:
|
|
||||||
int old_node = m_track_node;
|
|
||||||
if(m_track_node!=QuadGraph::UNKNOWN_SECTOR)
|
|
||||||
{
|
|
||||||
m_quad_graph->findRoadSector(m_kart->getXYZ(), &m_track_node,
|
|
||||||
&m_all_look_aheads[m_track_node]);
|
|
||||||
}
|
|
||||||
// If we can't find a proper place on the track, to a broader search
|
|
||||||
// on off-track locations.
|
|
||||||
if(m_track_node==QuadGraph::UNKNOWN_SECTOR)
|
|
||||||
{
|
|
||||||
m_track_node = m_quad_graph->findOutOfRoadSector(m_kart->getXYZ());
|
|
||||||
}
|
|
||||||
// IF the AI is off track (or on a branch of the track it did not
|
|
||||||
// select to be on), keep the old position.
|
|
||||||
if(m_track_node==QuadGraph::UNKNOWN_SECTOR ||
|
|
||||||
m_next_node_index[m_track_node]==-1)
|
|
||||||
m_track_node = old_node;
|
|
||||||
|
|
||||||
// The client does not do any AI computations.
|
// The client does not do any AI computations.
|
||||||
if(network_manager->getMode()==NetworkManager::NW_CLIENT)
|
if(network_manager->getMode()==NetworkManager::NW_CLIENT)
|
||||||
{
|
{
|
||||||
Controller::update(dt);
|
AIBaseController::update(dt);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( m_world->isStartPhase() )
|
if( m_world->isStartPhase() )
|
||||||
{
|
{
|
||||||
handleRaceStart();
|
handleRaceStart();
|
||||||
Controller::update(dt);
|
AIBaseController::update(dt);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -316,7 +260,7 @@ void DefaultAIController::update(float dt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*And obviously general kart stuff*/
|
/*And obviously general kart stuff*/
|
||||||
Controller::update(dt);
|
AIBaseController::update(dt);
|
||||||
m_collided = false;
|
m_collided = false;
|
||||||
} // update
|
} // update
|
||||||
|
|
||||||
|
@ -114,24 +114,6 @@ private:
|
|||||||
float m_curve_target_speed;
|
float m_curve_target_speed;
|
||||||
float m_curve_angle;
|
float m_curve_angle;
|
||||||
|
|
||||||
/** The current node the kart is on. This can be different from the value
|
|
||||||
* in LinearWorld, since it takes the chosen path of the AI into account
|
|
||||||
* (e.g. the closest point in LinearWorld might be on a branch not
|
|
||||||
* chosen by the AI). */
|
|
||||||
int m_track_node;
|
|
||||||
|
|
||||||
/** 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 contains the chosen next node.
|
|
||||||
* For normal lap track without branches we always have
|
|
||||||
* m_next_node_index[i] = (i+1) % size;
|
|
||||||
* but if a branch is possible, the AI will select one option here.
|
|
||||||
* If the node is not used, m_next_node_index will be -1. */
|
|
||||||
std::vector<int> m_next_node_index;
|
|
||||||
/** For each graph node this list contains a list of the next X
|
|
||||||
* graph nodes. */
|
|
||||||
std::vector<std::vector<int> > m_all_look_aheads;
|
|
||||||
|
|
||||||
float m_time_since_stuck;
|
float m_time_since_stuck;
|
||||||
|
|
||||||
int m_start_kart_crash_direction; //-1 = left, 1 = right, 0 = no crash.
|
int m_start_kart_crash_direction; //-1 = left, 1 = right, 0 = no crash.
|
||||||
|
@ -50,18 +50,21 @@
|
|||||||
EndController::EndController(Kart *kart, StateManager::ActivePlayer *player)
|
EndController::EndController(Kart *kart, StateManager::ActivePlayer *player)
|
||||||
: AIBaseController(kart, player)
|
: AIBaseController(kart, player)
|
||||||
{
|
{
|
||||||
m_next_node_index.reserve(m_quad_graph->getNumNodes());
|
if(race_manager->getMinorMode()!=RaceManager::MINOR_MODE_3_STRIKES)
|
||||||
m_successor_index.reserve(m_quad_graph->getNumNodes());
|
{
|
||||||
|
// Overwrite the random selected default path from AIBaseController
|
||||||
|
// with a path that always picks the first branch (i.e. it follows
|
||||||
|
// the main driveline).
|
||||||
std::vector<unsigned int> next;
|
std::vector<unsigned int> next;
|
||||||
for(unsigned int i=0; i<m_quad_graph->getNumNodes(); i++)
|
for(unsigned int i=0; i<m_quad_graph->getNumNodes(); i++)
|
||||||
{
|
{
|
||||||
// 0 is always a valid successor - so even if the kart should end
|
// 0 is always a valid successor - so even if the kart should end
|
||||||
// up by accident on a non-selected path, it will keep on working.
|
// up by accident on a non-selected path, it will keep on working.
|
||||||
m_successor_index.push_back(0);
|
m_successor_index[i] = 0;
|
||||||
|
|
||||||
next.clear();
|
next.clear();
|
||||||
m_quad_graph->getSuccessors(i, next);
|
m_quad_graph->getSuccessors(i, next);
|
||||||
m_next_node_index.push_back(next[0]);
|
m_next_node_index[i] = next[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
const unsigned int look_ahead=10;
|
const unsigned int look_ahead=10;
|
||||||
@ -72,7 +75,6 @@ EndController::EndController(Kart *kart, StateManager::ActivePlayer *player)
|
|||||||
// find too good a driveline. Note that in general this list should
|
// find too good a driveline. Note that in general this list should
|
||||||
// be computed recursively, but since the AI for now is using only
|
// be computed recursively, but since the AI for now is using only
|
||||||
// (randomly picked) path this is fine
|
// (randomly picked) path this is fine
|
||||||
m_all_look_aheads.reserve(m_quad_graph->getNumNodes());
|
|
||||||
for(unsigned int i=0; i<m_quad_graph->getNumNodes(); i++)
|
for(unsigned int i=0; i<m_quad_graph->getNumNodes(); i++)
|
||||||
{
|
{
|
||||||
std::vector<int> l;
|
std::vector<int> l;
|
||||||
@ -82,8 +84,10 @@ EndController::EndController(Kart *kart, StateManager::ActivePlayer *player)
|
|||||||
l.push_back(m_next_node_index[current]);
|
l.push_back(m_next_node_index[current]);
|
||||||
current = m_next_node_index[current];
|
current = m_next_node_index[current];
|
||||||
} // for j<look_ahead
|
} // for j<look_ahead
|
||||||
m_all_look_aheads.push_back(l);
|
m_all_look_aheads[i] = l;
|
||||||
}
|
}
|
||||||
|
} // if not battle mode
|
||||||
|
|
||||||
// Reset must be called after m_quad_graph etc. is set up
|
// Reset must be called after m_quad_graph etc. is set up
|
||||||
reset();
|
reset();
|
||||||
|
|
||||||
@ -111,11 +115,15 @@ EndController::~EndController()
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void EndController::reset()
|
void EndController::reset()
|
||||||
{
|
{
|
||||||
|
AIBaseController::reset();
|
||||||
|
|
||||||
m_crash_time = 0.0f;
|
m_crash_time = 0.0f;
|
||||||
m_time_since_stuck = 0.0f;
|
m_time_since_stuck = 0.0f;
|
||||||
|
|
||||||
Controller::reset();
|
|
||||||
m_track_node = QuadGraph::UNKNOWN_SECTOR;
|
m_track_node = QuadGraph::UNKNOWN_SECTOR;
|
||||||
|
// In battle mode there is no quad graph, so nothing to do in this case
|
||||||
|
if(m_quad_graph)
|
||||||
|
{
|
||||||
m_quad_graph->findRoadSector(m_kart->getXYZ(), &m_track_node);
|
m_quad_graph->findRoadSector(m_kart->getXYZ(), &m_track_node);
|
||||||
|
|
||||||
// Node that this can happen quite easily, e.g. an AI kart is
|
// Node that this can happen quite easily, e.g. an AI kart is
|
||||||
@ -124,6 +132,7 @@ void EndController::reset()
|
|||||||
{
|
{
|
||||||
m_track_node = m_quad_graph->findOutOfRoadSector(m_kart->getXYZ());
|
m_track_node = m_quad_graph->findOutOfRoadSector(m_kart->getXYZ());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} // reset
|
} // reset
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -146,23 +155,17 @@ void EndController::update(float dt)
|
|||||||
m_controls->m_brake = false;
|
m_controls->m_brake = false;
|
||||||
m_controls->m_accel = 1.0f;
|
m_controls->m_accel = 1.0f;
|
||||||
|
|
||||||
// Update the current node:
|
AIBaseController::update(dt);
|
||||||
if(m_track_node!=QuadGraph::UNKNOWN_SECTOR)
|
|
||||||
{
|
|
||||||
int old_node = m_track_node;
|
|
||||||
m_quad_graph->findRoadSector(m_kart->getXYZ(), &m_track_node,
|
|
||||||
&m_all_look_aheads[m_track_node]);
|
|
||||||
// IF the AI is off track (or on a branch of the track it did not
|
|
||||||
// select to be on), keep the old position.
|
|
||||||
if(m_track_node==QuadGraph::UNKNOWN_SECTOR ||
|
|
||||||
m_next_node_index[m_track_node]==-1)
|
|
||||||
m_track_node = old_node;
|
|
||||||
}
|
|
||||||
if(m_track_node==QuadGraph::UNKNOWN_SECTOR)
|
|
||||||
{
|
|
||||||
m_track_node = m_quad_graph->findOutOfRoadSector(m_kart->getXYZ());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// In case of battle mode: don't do anything
|
||||||
|
if(race_manager->getMinorMode()==RaceManager::MINOR_MODE_3_STRIKES)
|
||||||
|
{
|
||||||
|
m_controls->m_accel = 0.0f;
|
||||||
|
// Brake while we are still driving forwards (if we keep
|
||||||
|
// on braking, the kart will reverse otherwise)
|
||||||
|
m_controls->m_brake = m_kart->getSpeed()>0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
/*Get information that is needed by more than 1 of the handling funcs*/
|
/*Get information that is needed by more than 1 of the handling funcs*/
|
||||||
//Detect if we are going to crash with the track and/or kart
|
//Detect if we are going to crash with the track and/or kart
|
||||||
int steps = 0;
|
int steps = 0;
|
||||||
@ -172,9 +175,6 @@ void EndController::update(float dt)
|
|||||||
/*Response handling functions*/
|
/*Response handling functions*/
|
||||||
handleSteering(dt);
|
handleSteering(dt);
|
||||||
handleRescue(dt);
|
handleRescue(dt);
|
||||||
|
|
||||||
/*And obviously general kart stuff*/
|
|
||||||
Controller::update(dt);
|
|
||||||
} // update
|
} // update
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -58,24 +58,6 @@ private:
|
|||||||
//if the AI has been crashing for some time, use the rescue.
|
//if the AI has been crashing for some time, use the rescue.
|
||||||
float m_crash_time;
|
float m_crash_time;
|
||||||
|
|
||||||
/** The current node the kart is on. This can be different from the value
|
|
||||||
* in LinearWorld, since it takes the chosen path of the AI into account
|
|
||||||
* (e.g. the closest point in LinearWorld might be on a branch not
|
|
||||||
* chosen by the AI). */
|
|
||||||
int m_track_node;
|
|
||||||
|
|
||||||
/** 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 contains the chosen next node.
|
|
||||||
* For normal lap track without branches we always have
|
|
||||||
* m_next_node_index[i] = (i+1) % size;
|
|
||||||
* but if a branch is possible, the AI will select one option here.
|
|
||||||
* If the node is not used, m_next_node_index will be -1. */
|
|
||||||
std::vector<int> m_next_node_index;
|
|
||||||
/** For each graph node this list contains a list of the next X
|
|
||||||
* graph nodes. */
|
|
||||||
std::vector<std::vector<int> > m_all_look_aheads;
|
|
||||||
|
|
||||||
float m_time_since_stuck;
|
float m_time_since_stuck;
|
||||||
|
|
||||||
/** For debugging purpose: a sphere indicating where the AI
|
/** For debugging purpose: a sphere indicating where the AI
|
||||||
|
@ -48,43 +48,6 @@
|
|||||||
|
|
||||||
NewAIController::NewAIController(Kart *kart) : AIBaseController(kart)
|
NewAIController::NewAIController(Kart *kart) : AIBaseController(kart)
|
||||||
{
|
{
|
||||||
m_next_node_index.reserve(m_quad_graph->getNumNodes());
|
|
||||||
m_successor_index.reserve(m_quad_graph->getNumNodes());
|
|
||||||
std::vector<unsigned int> next;
|
|
||||||
|
|
||||||
for(unsigned int i=0; i<m_quad_graph->getNumNodes(); i++)
|
|
||||||
{
|
|
||||||
next.clear();
|
|
||||||
m_quad_graph->getSuccessors(i, next);
|
|
||||||
// For now pick one part on random, which is not adjusted during the
|
|
||||||
// race. Long term statistics might be gathered to determine the
|
|
||||||
// best way, potentially depending on race position etc.
|
|
||||||
int indx = rand() % next.size();
|
|
||||||
m_successor_index.push_back(indx);
|
|
||||||
m_next_node_index.push_back(next[indx]);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const unsigned int look_ahead=10;
|
|
||||||
// Now compute for each node in the graph the list of the next 'look_ahead'
|
|
||||||
// graph nodes. This is the list of node that is tested in checkCrashes.
|
|
||||||
// If the look_ahead is too big, the AI can skip loops (see
|
|
||||||
// QuadGraph::findRoadSector for details), if it's too short the AI won't
|
|
||||||
// find too good a driveline. Note that in general this list should
|
|
||||||
// be computed recursively, but since the AI for now is using only
|
|
||||||
// (randomly picked) path this is fine
|
|
||||||
m_all_look_aheads.reserve(m_quad_graph->getNumNodes());
|
|
||||||
for(unsigned int i=0; i<m_quad_graph->getNumNodes(); i++)
|
|
||||||
{
|
|
||||||
std::vector<int> l;
|
|
||||||
int current = i;
|
|
||||||
for(unsigned int j=0; j<look_ahead; j++)
|
|
||||||
{
|
|
||||||
l.push_back(m_next_node_index[current]);
|
|
||||||
current = m_next_node_index[current];
|
|
||||||
} // for j<look_ahead
|
|
||||||
m_all_look_aheads.push_back(l);
|
|
||||||
}
|
|
||||||
// Reset must be called after m_quad_graph etc. is set up
|
// Reset must be called after m_quad_graph etc. is set up
|
||||||
reset();
|
reset();
|
||||||
|
|
||||||
@ -157,37 +120,18 @@ unsigned int NewAIController::getNextSector(unsigned int index)
|
|||||||
//line, then move forward while turning.
|
//line, then move forward while turning.
|
||||||
void NewAIController::update(float dt)
|
void NewAIController::update(float dt)
|
||||||
{
|
{
|
||||||
|
AIBaseController::update(dt);
|
||||||
// This is used to enable firing an item backwards.
|
// This is used to enable firing an item backwards.
|
||||||
m_controls->m_look_back = false;
|
m_controls->m_look_back = false;
|
||||||
m_controls->m_nitro = false;
|
m_controls->m_nitro = false;
|
||||||
|
|
||||||
// Update the current node:
|
|
||||||
if(m_track_node!=QuadGraph::UNKNOWN_SECTOR)
|
|
||||||
{
|
|
||||||
int old_node = m_track_node;
|
|
||||||
m_quad_graph->findRoadSector(m_kart->getXYZ(), &m_track_node,
|
|
||||||
&m_all_look_aheads[m_track_node]);
|
|
||||||
// IF the AI is off track (or on a branch of the track it did not
|
|
||||||
// select to be on), keep the old position.
|
|
||||||
if(m_track_node==QuadGraph::UNKNOWN_SECTOR ||
|
|
||||||
m_next_node_index[m_track_node]==-1)
|
|
||||||
m_track_node = old_node;
|
|
||||||
}
|
|
||||||
if(m_track_node==QuadGraph::UNKNOWN_SECTOR)
|
|
||||||
{
|
|
||||||
m_track_node = m_quad_graph->findOutOfRoadSector(m_kart->getXYZ());
|
|
||||||
}
|
|
||||||
// The client does not do any AI computations.
|
// The client does not do any AI computations.
|
||||||
if(network_manager->getMode()==NetworkManager::NW_CLIENT)
|
if(network_manager->getMode()==NetworkManager::NW_CLIENT)
|
||||||
{
|
|
||||||
Controller::update(dt);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
if( m_world->isStartPhase() )
|
if( m_world->isStartPhase() )
|
||||||
{
|
{
|
||||||
handleRaceStart();
|
handleRaceStart();
|
||||||
Controller::update(dt);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,9 +202,6 @@ void NewAIController::update(float dt)
|
|||||||
m_controls->m_fire = true;
|
m_controls->m_fire = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*And obviously general kart stuff*/
|
|
||||||
Controller::update(dt);
|
|
||||||
m_collided = false;
|
m_collided = false;
|
||||||
} // update
|
} // update
|
||||||
|
|
||||||
@ -876,7 +817,7 @@ void NewAIController::reset()
|
|||||||
m_kart_behind = NULL;
|
m_kart_behind = NULL;
|
||||||
m_distance_behind = 0.0f;
|
m_distance_behind = 0.0f;
|
||||||
m_track_node = QuadGraph::UNKNOWN_SECTOR;
|
m_track_node = QuadGraph::UNKNOWN_SECTOR;
|
||||||
Controller::reset();
|
AIBaseController::reset();
|
||||||
m_quad_graph->findRoadSector(m_kart->getXYZ(), &m_track_node);
|
m_quad_graph->findRoadSector(m_kart->getXYZ(), &m_track_node);
|
||||||
if(m_track_node==QuadGraph::UNKNOWN_SECTOR)
|
if(m_track_node==QuadGraph::UNKNOWN_SECTOR)
|
||||||
{
|
{
|
||||||
|
@ -107,26 +107,6 @@ private:
|
|||||||
float m_curve_target_speed;
|
float m_curve_target_speed;
|
||||||
float m_curve_angle;
|
float m_curve_angle;
|
||||||
|
|
||||||
/** The current node the kart is on. This can be different from the value
|
|
||||||
* in LinearWorld, since it takes the chosen path of the AI into account
|
|
||||||
* (e.g. the closest point in LinearWorld might be on a branch not
|
|
||||||
* chosen by the AI). */
|
|
||||||
int m_track_node;
|
|
||||||
|
|
||||||
/** 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 contains the chosen next node.
|
|
||||||
* For normal lap track without branches we always have
|
|
||||||
* m_next_node_index[i] = (i+1) % size;
|
|
||||||
* but if a branch is possible, the AI will select one option here.
|
|
||||||
* If the node is not used, m_next_node_index will be -1. */
|
|
||||||
std::vector<int> m_next_node_index;
|
|
||||||
|
|
||||||
/** For each graph node this list contains a list of the next X
|
|
||||||
* graph nodes. */
|
|
||||||
std::vector<std::vector<int> > m_all_look_aheads;
|
|
||||||
|
|
||||||
/** The point the kart was aiming at when it was on track last. */
|
/** The point the kart was aiming at when it was on track last. */
|
||||||
Vec3 m_last_target_point;
|
Vec3 m_last_target_point;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user