Implemented portal extraction for string-pulling (funnel algorithm). Implemented braking but its untested.

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/battleAI@14898 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
nixt 2014-01-04 00:13:09 +00:00
parent 83d91b7b07
commit 9e3b338965
2 changed files with 192 additions and 67 deletions

View File

@ -104,11 +104,12 @@ void BattleAI::reset()
void BattleAI::update(float dt)
{
m_controls->m_accel = 0.5f;
//m_controls->m_accel = 0.5f;
// m_controls->m_steer = 0;
// updateCurrentNode();
handleAcceleration(dt);
handleSteering(dt);
handleBraking();
handleGetUnstuck(dt);
AIBaseController::update(dt);
} //BattleAI
@ -156,6 +157,7 @@ void BattleAI::handleSteering(const float dt)
PlayerController* pcontroller = (PlayerController*)kart->getController();
int player_node = pcontroller->getCurrentNode();
m_target_node = player_node;
// std::cout<<"PLayer node " << player_node<<" This cpu kart node" << m_current_node<<std::endl;
if(player_node == BattleGraph::UNKNOWN_POLY || m_current_node == BattleGraph::UNKNOWN_POLY) return;
if(player_node == m_current_node)
@ -165,11 +167,11 @@ void BattleAI::handleSteering(const float dt)
}
else
{
int next_node = BattleGraph::get()->getNextShortestPathPoly(m_current_node, player_node);
m_next_node = BattleGraph::get()->getNextShortestPathPoly(m_current_node, player_node);
// std::cout<<"Aiming at "<<next_node<<"\n";
if(next_node == -1) return;
target_point = NavMesh::get()->getCenterOfPoly(next_node);
if(m_next_node == -1) return;
target_point = NavMesh::get()->getCenterOfPoly(m_next_node);
}
m_target_angle = steerToPoint(target_point);
// std::cout<<"Target nalge: "<<m_target_angle << " normalized:"<<normalizeAngle(m_target_angle)<<std::endl;
@ -179,10 +181,182 @@ void BattleAI::handleSteering(const float dt)
m_debug_sphere->setPosition(target_point.toIrrVector());
Log::debug("skidding_ai","-Outside of road: steer to center point.\n");
#endif
findPortals(m_current_node, m_target_node, portals);
}
void BattleAI::findPortals(int start, int end, std::vector<std::pair<Vec3,Vec3> >& portals)
{
int this_node = start;
int next_node = NULL;
portals.clear();
while(next_node != end && this_node != -1 && next_node != -1 && this_node != end)
{
next_node = BattleGraph::get()->getNextShortestPathPoly(this_node, end);
const std::vector<int> this_node_verts =
NavMesh::get()->getNavPoly(this_node).getVerticesIndex();
const std::vector<int> next_node_verts=
NavMesh::get()->getNavPoly(next_node).getVerticesIndex();
Vec3 portalLeft, portalRight;
bool flag = 0;
for(unsigned int n_i=0; n_i<next_node_verts.size(); n_i++)
{
for(unsigned int t_i=0; t_i< this_node_verts.size(); t_i++)
{
if(next_node_verts[n_i] == this_node_verts[t_i])
{
if(flag == 0)
{
portalLeft = NavMesh::get()->getVertex(next_node_verts[n_i]);
flag=1;
}
else
portalRight = NavMesh::get()->getVertex(next_node_verts[n_i]);
}
}
}
portals.push_back(std::make_pair(portalLeft,portalRight));
//irr_driver->getVideoDriver()->draw3DLine(Vec3(portalLeft+Vec3(0,2,0)).toIrrVector(),Vec3(portalRight+Vec3(0,2,0)).toIrrVector(),video::SColor(255,0,0,255));
//m_debug_sphere->setPosition(Vec3((portalLeft+portalRight)/2).toIrrVector());
this_node=next_node;
}
}
void BattleAI::handleAcceleration( const float dt)
{
//Do not accelerate until we have delayed the start enough
/* if( m_start_delay > 0.0f )
{
m_start_delay -= dt;
m_controls->m_accel = 0.0f;
return;
}
*/
if( m_controls->m_brake )
{
m_controls->m_accel = 0.0f;
return;
}
if(m_kart->getBlockedByPlungerTime()>0)
{
if(m_kart->getSpeed() < m_kart->getCurrentMaxSpeed() / 2)
m_controls->m_accel = 0.05f;
else
m_controls->m_accel = 0.0f;
return;
}
m_controls->m_accel = stk_config->m_ai_acceleration;
} // handleAcceleration
void BattleAI::handleBraking()
{
m_controls->m_brake = false;
// A kart will not brake when the speed is already slower than this
// value. This prevents a kart from going too slow (or even backwards)
// in tight curves.
const float MIN_SPEED = 5.0f;
std::vector<Vec3> points;
if(m_current_node == -1 || m_next_node == -1 || m_target_node == -1)
return;
points.push_back(m_kart->getXYZ());
points.push_back(NavMesh::get()->getCenterOfPoly(m_next_node));
points.push_back(NavMesh::get()->getCenterOfPoly(m_target_node));
float current_curve_radius = BattleAI::determineTurnRadius(points);
std::cout<<"\n Radius: " << current_curve_radius;
float max_turn_speed =
m_kart->getKartProperties()
->getSpeedForTurnRadius(current_curve_radius);
if(m_kart->getSpeed() > max_turn_speed &&
m_kart->getSpeed()>MIN_SPEED )// &&
//fabsf(m_controls->m_steer) > 0.95f )
{
m_controls->m_brake = true;
std::cout<<"Braking"<<std::endl;
#ifdef DEBUG
if(m_ai_debug)
Log::debug("SkiddingAI",
"speed %f too tight curve: radius %f ",
m_kart->getSpeed(),
m_kart->getIdent().c_str(),
m_current_curve_radius);
#endif
}
return;
} // handleBraking
// Fit parabola to 3 points.
// Solve AX=B
float BattleAI::determineTurnRadius( std::vector<Vec3>& points )
{
// Declaring variables
float a,b,c;
irr::core::CMatrix4<float> A;
irr::core::CMatrix4<float> X;
irr::core::CMatrix4<float> B;
//Populating matrices
for(unsigned int i=0; i<3; i++)
{
A(i,0)= points[i].x()*points[i].x();
A(i,1)= points[i].x();
// std::cout<<"X"<<points[i].x();
A(i,2)= 1.0f;
A(i,3)= 0.0f;
}
A(3,0)=A(3,1)=A(3,2) = 0.0f;
A(3,3) = 1.0f;
for(unsigned int i=0; i<3; i++)
{
B(i,0)= points[i].z();
//std::cout<<"Z"<<points[i].z()<<"\n";
B(i,1)= 0.0f;
B(i,2)= 0.0f;
B(i,3)= 0.0f;
}
B(3,0)=B(3,1)=B(3,2)=B(3,3) = 0.0f;
//Computing inverse : X = inv(A)*B
irr::core::CMatrix4<float> invA;
if(!A.getInverse(invA))
{
return -1;
}
X = invA*B;
a = X(0,0);
b = X(0,1);
c = X(0,2);
float x = points.front().x();
float z = a*pow(x,2) + b*x + c;
float zD1 = 2*a*x + b;
float zD2 = 2*a;
float radius = pow(abs(1 + pow(zD1,2)),1.5f)/ abs(zD2);
return radius;
}
/*
float BattleAI::isStuck(const float dt)
@ -207,56 +381,3 @@ float BattleAI::isStuck(const float dt)
*/
/*
void BattleAI::updateCurrentNode()
{
std::cout<<"Current Node \t"<< m_current_node << std::endl;
// if unknown location, search everywhere
if(m_current_node != BattleGraph::UNKNOWN_POLY)
{
//check if the kart is still on the same node
const NavPoly& p = BattleGraph::get()->getPolyOfNode(m_current_node);
if(p.pointInPoly(m_kart->getXYZ())) return;
//if not then check all adjacent polys
const std::vector<int>& adjacents =
NavMesh::get()->getAdjacentPolys(m_current_node);
// Set m_current_node to unknown so that if no adjacent poly checks true
// we look everywhere the next time updateCurrentNode is called. This is
// useful in cases when you are "teleported" to some other poly, ex. rescue
m_current_node = BattleGraph::UNKNOWN_POLY;
for(unsigned int i=0; i<adjacents.size(); i++)
{
const NavPoly& p_temp =
BattleGraph::get()->getPolyOfNode(adjacents[i]);
if(p_temp.pointInPoly(m_kart->getXYZ())) m_current_node = adjacents[i];
}
}
if(m_current_node == BattleGraph::UNKNOWN_POLY)
{
int max_count = BattleGraph::get()->getNumNodes();
//float min_dist = 9999.99f;
for(unsigned int i =0; i<max_count; i++)
{
const NavPoly& p = BattleGraph::get()->getPolyOfNode(i);
if((p.pointInPoly(m_kart->getXYZ())))
{
m_current_node = i;
//min_dist = (p.getCenter() - m_kart->getXYZ()).length_2d();
}
}
}
return;
}
*/

View File

@ -35,10 +35,8 @@ class Vec3;
namespace irr
{
namespace scene
{
class ISceneNode;
}
namespace scene { class ISceneNode; }
namespace video { class ITexture; }
}
class BattleAI : public AIBaseController
@ -47,15 +45,21 @@ class BattleAI : public AIBaseController
private:
int m_current_node;
int m_next_node;
int m_target_node;
std::vector<std::pair<Vec3,Vec3> > portals;
float m_target_angle;
float m_time_since_stuck;
bool m_currently_reversing;
void handleAcceleration(const float dt) {};
float determineTurnRadius(std::vector<Vec3>& points);
void findPortals(int start, int end, std::vector<std::pair<Vec3,Vec3> > &portals);
void handleAcceleration(const float dt) ;
void handleSteering(const float dt);
void handleBraking() {};
void handleBraking();
void handleGetUnstuck(const float dt);
protected: