This commit is contained in:
hiker 2016-05-07 00:20:58 +10:00
commit 898cefc91e
4 changed files with 58 additions and 55 deletions

View File

@ -33,6 +33,7 @@ ArenaAI::ArenaAI(AbstractKart *kart)
: AIBaseController(kart)
{
m_debug_sphere = NULL;
m_debug_sphere_next = NULL;
} // ArenaAI
//-----------------------------------------------------------------------------
@ -262,7 +263,18 @@ void ArenaAI::handleArenaSteering(const float dt)
checkPosition(m_target_point, &m_cur_kart_pos_data);
#ifdef AI_DEBUG
m_debug_sphere->setPosition(m_target_point.toIrrVector());
if (m_path_corners.size() > 2)
{
m_debug_sphere->setVisible(true);
m_debug_sphere_next->setVisible(true);
m_debug_sphere->setPosition(m_path_corners[1].toIrrVector());
m_debug_sphere_next->setPosition(m_path_corners[2].toIrrVector());
}
else
{
m_debug_sphere->setVisible(false);
m_debug_sphere_next->setVisible(false);
}
#endif
if (m_cur_kart_pos_data.behind)
{
@ -488,18 +500,9 @@ void ArenaAI::handleArenaBraking()
// in tight curves.
const float MIN_SPEED = 5.0f;
std::vector<Vec3> points;
points.push_back(m_kart->getXYZ());
points.push_back(m_path_corners[0]);
points.push_back((m_path_corners.size()>=2) ? m_path_corners[1] : m_path_corners[0]);
float current_curve_radius = determineTurnRadius(points);
Vec3 d1 = m_kart->getXYZ() - m_target_point;
Vec3 d2 = m_kart->getXYZ() - m_path_corners[0];
if (d1.length2_2d() < d2.length2_2d())
current_curve_radius = d1.length_2d();
float current_curve_radius = determineTurnRadius(m_kart->getXYZ(),
m_path_corners[0], (m_path_corners.size() >= 2 ? m_path_corners[1] :
m_path_corners[0]));
float max_turn_speed = m_kart->getSpeedForTurnRadius(current_curve_radius);
@ -516,55 +519,44 @@ void ArenaAI::handleArenaBraking()
* location of AI, first corner and the second corner. Once the constants are
* computed, a formula is used to find the radius of curvature at the kart's
* current location.
* NOTE: This method does not apply enough braking, should think of something
* else.
*/
float ArenaAI::determineTurnRadius( std::vector<Vec3>& points )
float ArenaAI::determineTurnRadius(const Vec3& p1, const Vec3& p2,
const Vec3& p3)
{
// Declaring variables
float a, b;
irr::core::CMatrix4<float> A;
irr::core::CMatrix4<float> X;
irr::core::CMatrix4<float> B;
// The parabola function is as following: y=ax2+bx+c
// No need to calculate c as after differentiating c will be zero
const float eps = 0.01f;
const float denominator = (p1.x() - p2.x()) * (p1.x() - p3.x()) *
(p2.x() - p3.x());
//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();
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;
// Avoid nan, this will happen if three values of coordinates x are too
// close together, ie a straight line, return a large radius
// so no braking is needed
if (fabsf(denominator) < eps) return 25.0f;
for (unsigned int i = 0; i < 3; i++)
{
B(i, 0) = points[i].z();
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;
const float a = (p3.x() * (p2.z() - p1.z()) +
p2.x() * (p1.z() - p3.z()) +
p1.x() * (p3.z() - p2.z())) / denominator;
//Computing inverse : X = inv(A)*B
irr::core::CMatrix4<float> invA;
if (!A.getInverse(invA))
return -1;
// Should not happen, otherwise y=c which is a straight line
if (fabsf(a) < eps) return 25.0f;
X = invA*B;
a = X(0, 0);
b = X(0, 1);
//c = X(0, 2);
const float b = (p3.x() * p3.x() * (p1.z() - p2.z()) +
p2.x() * p2.x() * (p3.z() - p1.z()) +
p1.x() * p1.x() * (p2.z() - p3.z())) / denominator;
float x = points.front().x();
//float z = a*pow(x, 2) + b*x + c;
float dx_by_dz = 2*a*x + b;
float d2x_by_dz = 2*a;
// Differentiate the function, so y=ax2+bx+c will become y=2ax+b for dy_dx,
// y=2a for d2y_dx2
// Use the p1 (current location of AI) as x
const float dy_dx = 2 * a * p1.x() + b;
const float d2y_dx2 = 2 * a;
float radius = pow(abs(1 + pow(dx_by_dz, 2)), 1.5f)/ abs(d2x_by_dz);
// Calculate the radius of curvature at current location of AI
const float radius = pow(1 + pow(dy_dx, 2), 1.5f) / fabsf(d2y_dx2);
assert(!std::isnan(radius));
return radius;
// Avoid returning too large radius
return (radius > 25.0f ? 25.0f : radius);
} // determineTurnRadius
//-----------------------------------------------------------------------------
@ -663,7 +655,8 @@ void ArenaAI::handleArenaItems(const float dt)
if (m_time_since_last_shot < 1.0f) break;
if (m_closest_kart_pos_data.distance < 6.0f &&
(difficulty || perfect_aim))
(difficulty || perfect_aim) &&
!m_closest_kart->isInvulnerable())
{
m_controls->m_fire = true;
m_controls->m_look_back = fire_behind;

View File

@ -56,6 +56,7 @@ protected:
/** For debugging purpose: a sphere indicating where the AI
* is targeting at. */
irr::scene::ISceneNode *m_debug_sphere;
irr::scene::ISceneNode *m_debug_sphere_next;
/** The node(poly) at which the target point lies in. */
int m_target_node;
@ -104,7 +105,8 @@ private:
float m_time_since_uturn;
void checkIfStuck(const float dt);
float determineTurnRadius(std::vector<Vec3>& points);
float determineTurnRadius(const Vec3& p1, const Vec3& p2,
const Vec3& p3);
void findPortals(int start, int end);
void handleArenaAcceleration(const float dt);
void handleArenaBanana();

View File

@ -41,8 +41,11 @@ BattleAI::BattleAI(AbstractKart *kart)
#ifdef AI_DEBUG
video::SColor col_debug(128, 128, 0, 0);
video::SColor col_debug_next(128, 0, 128, 128);
m_debug_sphere = irr_driver->addSphere(1.0f, col_debug);
m_debug_sphere->setVisible(true);
m_debug_sphere_next = irr_driver->addSphere(1.0f, col_debug_next);
m_debug_sphere_next->setVisible(true);
#endif
m_world = dynamic_cast<ThreeStrikesBattle*>(World::getWorld());
m_track = m_world->getTrack();
@ -59,6 +62,7 @@ BattleAI::~BattleAI()
{
#ifdef AI_DEBUG
irr_driver->removeNode(m_debug_sphere);
irr_driver->removeNode(m_debug_sphere_next);
#endif
} // ~BattleAI

View File

@ -41,8 +41,11 @@ SoccerAI::SoccerAI(AbstractKart *kart)
#ifdef AI_DEBUG
video::SColor col_debug(128, 128, 0, 0);
video::SColor col_debug_next(128, 0, 128, 128);
m_debug_sphere = irr_driver->addSphere(1.0f, col_debug);
m_debug_sphere->setVisible(true);
m_debug_sphere_next = irr_driver->addSphere(1.0f, col_debug_next);
m_debug_sphere_next->setVisible(true);
#endif
m_world = dynamic_cast<SoccerWorld*>(World::getWorld());
m_track = m_world->getTrack();
@ -59,6 +62,7 @@ SoccerAI::~SoccerAI()
{
#ifdef AI_DEBUG
irr_driver->removeNode(m_debug_sphere);
irr_driver->removeNode(m_debug_sphere_next);
#endif
} // ~SoccerAI