Try to make AI work like zidane

This commit is contained in:
Benau 2016-05-26 08:24:45 +08:00
parent cdae595724
commit 0c254dfa5d
5 changed files with 64 additions and 42 deletions

View File

@ -241,7 +241,7 @@ void ArenaAI::handleArenaSteering(const float dt)
if (current_node == BattleGraph::UNKNOWN_POLY ||
m_target_node == BattleGraph::UNKNOWN_POLY) return;
if (m_target_node == current_node || directDrive())
if (m_target_node == current_node || ignorePathFinding())
{
// Very close to the item, steer directly
m_path_corners.clear();

View File

@ -64,7 +64,7 @@ protected:
/** The target point. */
Vec3 m_target_point;
/** For directDrive() to work */
/** For ignorePathFinding() to work */
bool m_avoid_eating_banana;
void collectItemInArena(Vec3*, int*) const;
@ -125,7 +125,7 @@ private:
virtual void findClosestKart(bool use_difficulty) = 0;
virtual void findTarget() = 0;
virtual bool forceBraking() { return false; }
virtual bool directDrive() { return m_avoid_eating_banana; }
virtual bool ignorePathFinding() { return m_avoid_eating_banana; }
public:
ArenaAI(AbstractKart *kart);
virtual ~ArenaAI() {};

View File

@ -56,9 +56,9 @@ SoccerAI::SoccerAI(AbstractKart *kart)
video::SColor red(128, 128, 0, 0);
video::SColor blue(128, 0, 0, 128);
m_red_sphere = irr_driver->addSphere(1.0f, red);
m_red_sphere->setVisible(false);
m_red_sphere->setVisible(true);
m_blue_sphere = irr_driver->addSphere(1.0f, blue);
m_blue_sphere->setVisible(false);
m_blue_sphere->setVisible(true);
#endif
m_world = dynamic_cast<SoccerWorld*>(World::getWorld());
@ -99,7 +99,7 @@ void SoccerAI::reset()
m_overtake_ball = false;
m_force_brake = false;
m_steer_with_ball = false;
m_chasing_ball = false;
} // reset
@ -113,9 +113,9 @@ void SoccerAI::update(float dt)
m_blue_sphere->setPosition(blue.toIrrVector());
#endif
m_force_brake = false;
m_steer_with_ball = false;
m_chasing_ball = false;
if (World::getWorld()->getPhase() == World::GOAL_PHASE)
if (m_world->getPhase() == World::GOAL_PHASE)
{
resetAfterStop();
m_controls->m_brake = false;
@ -187,8 +187,7 @@ void SoccerAI::findTarget()
->getWorldKartId())
{
// This AI will attack the other team ball chaser
int id = m_world->getBallChaser(m_cur_team == SOCCER_TEAM_BLUE ?
SOCCER_TEAM_RED : SOCCER_TEAM_BLUE);
int id = m_world->getBallChaser(m_opp_team);
m_target_point = m_world->getKart(id)->getXYZ();
m_target_node = m_world->getKartNode(id);
}
@ -215,24 +214,22 @@ Vec3 SoccerAI::determineBallAimingPosition()
const Vec3& ball_aim_pos = m_world->getBallAimPosition(m_opp_team);
const Vec3& orig_pos = m_world->getBallPosition();
const float ball_diameter = m_world->getBallDiameter();
posData ball_pos = {0};
posData aim_pos = {0};
Vec3 ball_lc;
Vec3 aim_lc;
checkPosition(orig_pos, &ball_pos, &ball_lc, true/*use_front_xyz*/);
checkPosition(ball_aim_pos, &aim_pos, &aim_lc, true/*use_front_xyz*/);
checkPosition(orig_pos, NULL, &ball_lc, true/*use_front_xyz*/);
checkPosition(ball_aim_pos, NULL, &aim_lc, true/*use_front_xyz*/);
// Too far from the ball,
// use path finding from arena ai to get close
// ie no extra braking is needed
if (aim_pos.distance > 10.0f) return ball_aim_pos;
if (aim_lc.length_2d() > 10.0f) return ball_aim_pos;
if (m_overtake_ball)
{
Vec3 overtake_lc;
const bool can_overtake = determineOvertakePosition(ball_lc, aim_lc,
ball_pos, &overtake_lc);
&overtake_lc);
if (!can_overtake)
{
m_overtake_ball = false;
@ -248,7 +245,7 @@ Vec3 SoccerAI::determineBallAimingPosition()
// is behind the ball , if so m_overtake_ball is true
if (aim_lc.z() > 0 && aim_lc.z() > ball_lc.z())
{
if (isOvertakable(ball_lc, ball_pos))
if (isOvertakable(ball_lc))
{
m_overtake_ball = true;
return ball_aim_pos;
@ -263,33 +260,58 @@ Vec3 SoccerAI::determineBallAimingPosition()
}
}
// Otherwise use the aim position calculated by soccer world
// Prevent lost control when steering with ball
m_force_brake = ball_pos.angle > 0.15f &&
m_kart->getSpeed() > 9.0f && ball_pos.distance < ball_diameter;
if (aim_pos.behind && aim_pos.distance < (ball_diameter / 2))
m_chasing_ball = true;
// Check if reached aim point, which is behind aiming position and
// in front of the ball, if so use another aiming method
if (aim_lc.z() < 0 && ball_lc.z() > 0)
{
// Reached aim point, aim forward
m_steer_with_ball = true;
// Find the angle between the ball to kart and the aim position
// to kart, if it's not almost 180 or 0 degree, we need to
// apply brake
const float c = sqrtf(pow(ball_lc.z() - aim_lc.z(), 2) +
pow(ball_lc.x() - aim_lc.x(), 2));
const float angle = findAngleFrom3Edges(aim_lc.length_2d(),
ball_lc.length_2d(), c);
if (angle > 1 && angle < 179)
{
m_force_brake = true;
}
// Return the behind version of aim position, allow pushing to
// ball towards the it
return m_world->getBallAimPosition(m_opp_team, true/*reverse*/);
}
return ball_aim_pos;
}
// Make compiler happy
// Otherwise keep steering until reach aim position
return ball_aim_pos;
} // determineBallAimingPosition
//-----------------------------------------------------------------------------
bool SoccerAI::isOvertakable(const Vec3& ball_lc, const posData& ball_pos)
float SoccerAI::findAngleFrom3Edges(float a, float b, float c)
{
// Cosine forumla : c2 = a2 + b2 - 2ab cos C
float test_value = (c * c) - (a * a) - (b * b) / (-(2 * a * b));
// Prevent error
if (test_value < -1)
test_value = -1;
else if (test_value > 1)
test_value = 1;
return acosf(test_value) * RAD_TO_DEGREE;
} // find3PointsAngle
//-----------------------------------------------------------------------------
bool SoccerAI::isOvertakable(const Vec3& ball_lc)
{
// No overtake if ball is behind
if (ball_lc.z() < 0.0f) return false;
// Circle equation: (x-a)2 + (y-b)2 = r2
const float r2 = (ball_pos.distance / 2) * (ball_pos.distance / 2);
const float r2 = (ball_lc.length_2d() / 2) * (ball_lc.length_2d() / 2);
const float a = ball_lc.x();
const float b = ball_lc.z();
@ -307,16 +329,15 @@ bool SoccerAI::isOvertakable(const Vec3& ball_lc, const posData& ball_pos)
//-----------------------------------------------------------------------------
bool SoccerAI::determineOvertakePosition(const Vec3& ball_lc,
const Vec3& aim_lc,
const posData& ball_pos,
Vec3* overtake_lc)
{
// This done by drawing a circle using the center of ball local coordinates
// and the distance / 2 from kart to ball center as radius (which allows more
// offset for overtaking), then find tangent line from kart (0, 0, 0) to the
// circle. The intercept point will be used as overtake position
// and the distance / 2 from kart to ball center as radius (which allows
// more offset for overtaking), then find tangent line from kart (0, 0, 0)
// to the circle. The intercept point will be used as overtake position
// Check if overtakable at current location
if (!isOvertakable(ball_lc, ball_pos)) return false;
if (!isOvertakable(ball_lc)) return false;
// Otherwise calculate the tangent
// As all are local coordinates, so center is 0,0 which is y = mx for the
@ -332,7 +353,7 @@ bool SoccerAI::determineOvertakePosition(const Vec3& ball_lc,
// x = -b (+/-) sqrt(b2 - 4ac) / 2a
// Circle equation: (x-a)2 + (y-b)2 = r2
const float r = ball_pos.distance / 2;
const float r = ball_lc.length_2d() / 2;
const float r2 = r * r;
const float a = ball_lc.x();
const float b = ball_lc.z();

View File

@ -52,13 +52,14 @@ private:
*/
bool m_overtake_ball;
bool m_force_brake;
bool m_steer_with_ball;
bool m_chasing_ball;
Vec3 determineBallAimingPosition();
bool isOvertakable(const Vec3& ball_lc, const posData& ball_pos);
bool isOvertakable(const Vec3& ball_lc);
bool determineOvertakePosition(const Vec3& ball_lc, const Vec3& aim_lc,
const posData& ball_pos, Vec3* overtake_lc);
Vec3* overtake_lc);
float rotateSlope(float old_slope, bool rotate_up);
float findAngleFrom3Edges(float a, float b, float c);
virtual void findClosestKart(bool use_difficulty);
virtual void findTarget();
@ -67,9 +68,9 @@ private:
virtual bool isWaiting() const;
virtual bool canSkid(float steer_fraction) { return false; }
virtual bool forceBraking() OVERRIDE { return m_force_brake; }
virtual bool directDrive() OVERRIDE
virtual bool ignorePathFinding() OVERRIDE
{
return m_avoid_eating_banana || m_overtake_ball || m_steer_with_ball;
return m_avoid_eating_banana || m_overtake_ball || m_chasing_ball;
}
public:

View File

@ -202,7 +202,7 @@ private:
// If it's likely to goal already, aim the ball straight behind
// should do the job
if (isApproachingGoal(team))
return m_trans(Vec3(0, 0, -1));
return m_trans(Vec3(0, 0, -m_radius*2));
// Otherwise do the below:
// This is done by using Pythagorean Theorem and solving the