Make AI really bends it like Beckham
Notice: AI will only try to skid to save the ball from being scored when expert and supertux mode.
This commit is contained in:
parent
ea05f4b6ba
commit
df9dc5ff34
@ -184,7 +184,7 @@ float AIBaseController::normalizeAngle(float angle)
|
||||
void AIBaseController::setSteering(float angle, float dt)
|
||||
{
|
||||
float steer_fraction = angle / m_kart->getMaxSteerAngle();
|
||||
if(!doSkid(steer_fraction))
|
||||
if(!canSkid(steer_fraction))
|
||||
m_controls->m_skid = KartControl::SC_NONE;
|
||||
else
|
||||
m_controls->m_skid = steer_fraction > 0 ? KartControl::SC_RIGHT
|
||||
@ -214,15 +214,6 @@ void AIBaseController::setSteering(float angle, float dt)
|
||||
}
|
||||
} // setSteering
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Determines if the kart should skid. The base implementation enables
|
||||
* skidding if a sharp turn is needed (which is for the old skidding
|
||||
* implementation).
|
||||
* \param steer_fraction The steering fraction as computed by the
|
||||
* AIBaseController.
|
||||
* \return True if the kart should skid.
|
||||
*/
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Certain AI levels will not receive a slipstream bonus in order to
|
||||
* be not as hard.
|
||||
@ -232,23 +223,6 @@ bool AIBaseController::disableSlipstreamBonus() const
|
||||
return m_ai_properties->disableSlipstreamUsage();
|
||||
} // disableSlipstreamBonus
|
||||
|
||||
|
||||
bool AIBaseController::doSkid(float steer_fraction)
|
||||
{
|
||||
// Disable skidding when a plunger is in the face
|
||||
if(m_kart->getBlockedByPlungerTime()>0) return false;
|
||||
|
||||
// FIXME: Disable skidding for now if the new skidding
|
||||
// code is activated, since the AI can not handle this
|
||||
// properly.
|
||||
if(m_kart->getKartProperties()->getSkidVisualTime() > 0)
|
||||
return false;
|
||||
|
||||
// Otherwise return if we need a sharp turn (which is
|
||||
// for the old skidding implementation).
|
||||
return fabsf(steer_fraction)>=m_ai_properties->m_skidding_threshold;
|
||||
} // doSkid
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** This is called when the kart crashed with the terrain. This subroutine
|
||||
* tries to detect if the AI is stuck by determining if a certain number
|
||||
|
@ -51,7 +51,7 @@ protected:
|
||||
float m_kart_width;
|
||||
|
||||
/** Keep a pointer to the track to reduce calls */
|
||||
Track *m_track;
|
||||
Track *m_track;
|
||||
|
||||
/** A pointer to the AI properties for this kart. */
|
||||
const AIProperties *m_ai_properties;
|
||||
@ -61,17 +61,17 @@ protected:
|
||||
/** Position info structure of targets. */
|
||||
struct posData {bool behind; bool on_side; float angle; float distance;};
|
||||
|
||||
void setControllerName(const std::string &name);
|
||||
float steerToPoint(const Vec3 &point);
|
||||
float normalizeAngle(float angle);
|
||||
virtual void update (float delta) ;
|
||||
virtual void setSteering (float angle, float dt);
|
||||
void setControllerName(const std::string &name);
|
||||
float steerToPoint(const Vec3 &point);
|
||||
float normalizeAngle(float angle);
|
||||
virtual bool doSkid(float steer_fraction);
|
||||
virtual bool canSkid(float steer_fraction) { return false; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** This can be called to detect if the kart is stuck (i.e. repeatedly
|
||||
* hitting part of the track). */
|
||||
bool isStuck() const { return m_stuck; }
|
||||
void checkPosition(const Vec3&, posData*, Vec3* lc = NULL) const;
|
||||
bool isStuck() const { return m_stuck; }
|
||||
void checkPosition(const Vec3&, posData*, Vec3* lc = NULL) const;
|
||||
|
||||
public:
|
||||
AIBaseController(AbstractKart *kart,
|
||||
|
@ -45,19 +45,8 @@ BattleAI::BattleAI(AbstractKart *kart,
|
||||
m_debug_sphere = irr_driver->addSphere(1.0f, col_debug);
|
||||
m_debug_sphere->setVisible(true);
|
||||
#endif
|
||||
|
||||
if (race_manager->getMinorMode() == RaceManager::MINOR_MODE_3_STRIKES)
|
||||
{
|
||||
m_world = dynamic_cast<ThreeStrikesBattle*>(World::getWorld());
|
||||
m_track = m_world->getTrack();
|
||||
}
|
||||
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_world = dynamic_cast<ThreeStrikesBattle*>(World::getWorld());
|
||||
m_track = m_world->getTrack();
|
||||
|
||||
// Don't call our own setControllerName, since this will add a
|
||||
// billboard showing 'AIBaseController' to the kart.
|
||||
|
@ -2210,7 +2210,7 @@ void SkiddingAI::handleCurve()
|
||||
* AIBaseLapController.
|
||||
* \return True if the kart should skid.
|
||||
*/
|
||||
bool SkiddingAI::doSkid(float steer_fraction)
|
||||
bool SkiddingAI::canSkid(float steer_fraction)
|
||||
{
|
||||
if(fabsf(steer_fraction)>1.5f)
|
||||
{
|
||||
@ -2319,7 +2319,7 @@ bool SkiddingAI::doSkid(float steer_fraction)
|
||||
m_kart->getIdent().c_str());
|
||||
#endif
|
||||
return false;
|
||||
} // doSkid
|
||||
} // canSkid
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Converts the steering angle to a lr steering in the range of -1 to 1.
|
||||
@ -2341,7 +2341,7 @@ void SkiddingAI::setSteering(float angle, float dt)
|
||||
// Use a simple finite state machine to make sure to randomly decide
|
||||
// whether to skid or not only once per skid section. See docs for
|
||||
// m_skid_probability_state for more details.
|
||||
if(!doSkid(steer_fraction))
|
||||
if(!canSkid(steer_fraction))
|
||||
{
|
||||
m_skid_probability_state = SKID_PROBAB_NOT_YET;
|
||||
m_controls->m_skid = KartControl::SC_NONE;
|
||||
|
@ -94,7 +94,7 @@ the AI does the following steps:
|
||||
behaviour.
|
||||
The function handleSteering() then calls setSteering() to set the
|
||||
actually steering amount. The latter function also decides if skidding
|
||||
should be done or not (by calling doSkid()).
|
||||
should be done or not (by calling canSkid()).
|
||||
- decide if to try to collect or avoid items (handeItems).
|
||||
It considers all items on quads between the current quad of the kart
|
||||
and the quad the AI is aiming at (see handleSteering). If it finds
|
||||
@ -270,7 +270,7 @@ private:
|
||||
const Vec3 &end,
|
||||
Vec3 *center,
|
||||
float *radius);
|
||||
virtual bool doSkid(float steer_fraction);
|
||||
virtual bool canSkid(float steer_fraction);
|
||||
virtual void setSteering(float angle, float dt);
|
||||
void handleCurve();
|
||||
|
||||
|
@ -45,19 +45,8 @@ SoccerAI::SoccerAI(AbstractKart *kart,
|
||||
m_debug_sphere = irr_driver->addSphere(1.0f, col_debug);
|
||||
m_debug_sphere->setVisible(true);
|
||||
#endif
|
||||
|
||||
if (race_manager->getMinorMode() == RaceManager::MINOR_MODE_SOCCER)
|
||||
{
|
||||
m_world = dynamic_cast<SoccerWorld*>(World::getWorld());
|
||||
m_track = m_world->getTrack();
|
||||
}
|
||||
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_world = dynamic_cast<SoccerWorld*>(World::getWorld());
|
||||
m_track = m_world->getTrack();
|
||||
|
||||
// Don't call our own setControllerName, since this will add a
|
||||
// billboard showing 'AIBaseController' to the kart.
|
||||
@ -82,6 +71,7 @@ void SoccerAI::reset()
|
||||
ArenaAI::reset();
|
||||
AIBaseController::reset();
|
||||
|
||||
m_saving_ball = false;
|
||||
if (race_manager->getNumPlayers() == 1)
|
||||
{
|
||||
// Same handle in SoccerWorld::createKart
|
||||
@ -106,6 +96,7 @@ void SoccerAI::reset()
|
||||
//-----------------------------------------------------------------------------
|
||||
void SoccerAI::update(float dt)
|
||||
{
|
||||
m_saving_ball = false;
|
||||
if (World::getWorld()->getPhase() == World::GOAL_PHASE)
|
||||
{
|
||||
m_controls->m_accel = 0.0f;
|
||||
@ -196,12 +187,40 @@ Vec3 SoccerAI::correctBallPosition(const Vec3& orig_pos)
|
||||
|
||||
if (goal_pos.behind)
|
||||
{
|
||||
// If facing the wrong goal, apply more offset to the ball
|
||||
// to prevent shooting into its own team goal
|
||||
ball_lc = (goal_pos.on_side ? ball_lc - Vec3 (2, 0, 0) + Vec3 (0, 0, 2):
|
||||
ball_lc + Vec3 (2, 0, 2));
|
||||
if (goal_pos.angle > 0.3f && ball_pos.distance < 3.0f &&
|
||||
!ball_pos.behind)
|
||||
{
|
||||
// Only steer with ball if same sides for ball and goal
|
||||
if (ball_pos.on_side && goal_pos.on_side)
|
||||
{
|
||||
ball_lc = ball_lc + Vec3 (1, 0, 1);
|
||||
return m_kart->getTrans()(ball_lc);
|
||||
}
|
||||
else if (!ball_pos.on_side && !goal_pos.on_side)
|
||||
{
|
||||
ball_lc = ball_lc - Vec3 (1, 0, 0) + Vec3 (0, 0, 1);
|
||||
return m_kart->getTrans()(ball_lc);
|
||||
}
|
||||
else
|
||||
m_controls->m_brake = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// This case is facing straight ahead opposite goal
|
||||
// (which is straight behind itself), apply more
|
||||
// offset for skidding, to save the ball from behind
|
||||
// scored.
|
||||
// Notice: this assume map maker make soccer field
|
||||
// with two goals facing each other straight
|
||||
ball_lc = (goal_pos.on_side ? ball_lc - Vec3 (2, 0, 0) +
|
||||
Vec3 (0, 0, 2) : ball_lc + Vec3 (2, 0, 2));
|
||||
|
||||
return m_kart->getTrans()(ball_lc);
|
||||
if (ball_pos.distance < 3.0f &&
|
||||
(m_cur_difficulty == RaceManager::DIFFICULTY_HARD ||
|
||||
m_cur_difficulty == RaceManager::DIFFICULTY_BEST))
|
||||
m_saving_ball = true;
|
||||
return m_kart->getTrans()(ball_lc);
|
||||
}
|
||||
}
|
||||
|
||||
if (ball_pos.distance < 3.0f &&
|
||||
@ -211,9 +230,19 @@ Vec3 SoccerAI::correctBallPosition(const Vec3& orig_pos)
|
||||
return orig_pos;
|
||||
else
|
||||
{
|
||||
ball_lc = (goal_pos.on_side ? ball_lc + Vec3 (1, 0, 1) :
|
||||
ball_lc - Vec3 (1, 0, 0) + Vec3 (0, 0, 1));
|
||||
return m_kart->getTrans()(ball_lc);
|
||||
// Same with above
|
||||
if (ball_pos.on_side && goal_pos.on_side)
|
||||
{
|
||||
ball_lc = ball_lc + Vec3 (1, 0, 1);
|
||||
return m_kart->getTrans()(ball_lc);
|
||||
}
|
||||
else if (!ball_pos.on_side && !goal_pos.on_side)
|
||||
{
|
||||
ball_lc = ball_lc - Vec3 (1, 0, 0) + Vec3 (0, 0, 1);
|
||||
return m_kart->getTrans()(ball_lc);
|
||||
}
|
||||
else
|
||||
m_controls->m_brake = true;
|
||||
}
|
||||
}
|
||||
return orig_pos;
|
||||
|
@ -35,12 +35,15 @@ private:
|
||||
SoccerWorld *m_world;
|
||||
|
||||
SoccerTeam m_cur_team;
|
||||
bool m_saving_ball;
|
||||
|
||||
Vec3 correctBallPosition(const Vec3&);
|
||||
|
||||
virtual void findClosestKart(bool use_difficulty);
|
||||
virtual void findTarget();
|
||||
virtual int getCurrentNode() const;
|
||||
virtual bool isWaiting() const;
|
||||
virtual bool canSkid(float steer_fraction) { return m_saving_ball; }
|
||||
public:
|
||||
SoccerAI(AbstractKart *kart,
|
||||
StateManager::ActivePlayer *player = NULL);
|
||||
|
Loading…
x
Reference in New Issue
Block a user