Add doxygen for Arena and Battle AI

Plus some coding-style cleanup
This commit is contained in:
Benau 2016-10-20 16:40:20 +08:00
parent b12f7a1079
commit 021509387d
7 changed files with 159 additions and 53 deletions

View File

@ -75,6 +75,8 @@ protected:
float *radius) const;
virtual void update (float delta);
virtual void setSteering (float angle, float dt);
// ------------------------------------------------------------------------
/** Return true if AI can skid now. */
virtual bool canSkid(float steer_fraction) = 0;
public:

View File

@ -74,6 +74,7 @@ void ArenaAI::reset()
/** This is the main entry point for the AI.
* It is called once per frame for each AI and determines the behaviour of
* the AI, e.g. steering, accelerating/braking, firing.
* \param dt Time step size.
*/
void ArenaAI::update(float dt)
{
@ -170,10 +171,7 @@ bool ArenaAI::updateAimingPosition(Vec3* target_point)
m_debug_sphere_next->setVisible(false);
#endif
// Notice: we use the point ahead of kart to determine next node,
// to compensate the time difference between steering
m_current_forward_point =
m_kart->getTrans()(Vec3(0, 0, m_kart->getKartLength()));
m_current_forward_point = m_kart->getTrans()(Vec3(0, 0, m_kart_length));
m_turn_radius = 0.0f;
std::vector<int>* test_nodes = NULL;
@ -238,7 +236,7 @@ bool ArenaAI::updateAimingPosition(Vec3* target_point)
} // updateAimingPosition
//-----------------------------------------------------------------------------
/** This function config the steering of AI.
/** This function config the steering (\ref m_steering_angle) of AI.
*/
void ArenaAI::configSteering()
{
@ -294,6 +292,11 @@ void ArenaAI::configSteering()
} // configSteering
//-----------------------------------------------------------------------------
/** Determine whether AI is stuck, by checking if it stays on the same node for
* a long period of time (see \ref m_on_node), or \ref isStuck() is true.
* \param dt Time step size.
* \return True if AI is stuck
*/
void ArenaAI::checkIfStuck(const float dt)
{
if (m_is_stuck) return;
@ -312,8 +315,7 @@ void ArenaAI::checkIfStuck(const float dt)
&& m_on_node.size() < 2 && !m_is_uturn &&
fabsf(m_kart->getSpeed()) < 3.0f) || isStuck() == true)
{
// Check whether a kart stay on the same node for a period of time
// Or crashed 3 times
// AI is stuck, reset now and try to get unstuck at next frame
m_on_node.clear();
m_time_since_driving = 0.0f;
AIBaseController::reset();
@ -355,6 +357,8 @@ void ArenaAI::configSpeed()
} // configSpeed
//-----------------------------------------------------------------------------
/** Make AI reverse so that it faces in front of the last target point.
*/
void ArenaAI::doUTurn(const float dt)
{
float turn_angle = atan2f(m_target_point_lc.x(),
@ -377,6 +381,10 @@ void ArenaAI::doUTurn(const float dt)
} // doUTurn
//-----------------------------------------------------------------------------
/** Function to let AI get unstuck.
* \param dt Time step size.
* \return True if getting stuck is needed to be done.
*/
bool ArenaAI::gettingUnstuck(const float dt)
{
if (!m_is_stuck || m_is_uturn) return false;
@ -398,6 +406,10 @@ bool ArenaAI::gettingUnstuck(const float dt)
} // gettingUnstuck
//-----------------------------------------------------------------------------
/** Determine how AI should use its item, different \ref m_cur_difficulty will
* have a corresponding strategy.
* \param dt Time step size.
*/
void ArenaAI::useItems(const float dt)
{
m_controls->setFire(false);
@ -406,7 +418,7 @@ void ArenaAI::useItems(const float dt)
return;
// Find a closest kart again, this time we ignore difficulty
findClosestKart(false/*use_difficulty*/, false/*find_sta*/);
findClosestKart(false/*consider_difficulty*/, false/*find_sta*/);
if (!m_closest_kart) return;
Vec3 closest_kart_point_lc =
@ -558,7 +570,12 @@ void ArenaAI::useItems(const float dt)
} // useItems
//-----------------------------------------------------------------------------
void ArenaAI::collectItemInArena(Vec3* aim_point, int* target_node) const
/** Try to collect item in arena, if no suitable item is found, like they are
* swapped, it will follow closest kart instead.
* \param[out] aim_point Location of item.
* \param[out] target_node The node which item lied on.
*/
void ArenaAI::tryCollectItem(Vec3* aim_point, int* target_node) const
{
float distance = 999999.9f;
Item* selected = (*target_node == Graph::UNKNOWN_SECTOR ? NULL :
@ -611,13 +628,15 @@ void ArenaAI::collectItemInArena(Vec3* aim_point, int* target_node) const
*aim_point = m_closest_kart_point;
*target_node = m_closest_kart_node;
}
} // collectItemInArena
} // tryCollectItem
//-----------------------------------------------------------------------------
/** Determine if AI should skid: When it's close to target, but not straight
* ahead, in front of it, same steering side and with suitable difficulties
* which are in expert and supertux only.
*/
void ArenaAI::doSkiddingTest()
{
// Skid when close to target, but not straight ahead, in front of it, same
// steering side and with suitable difficulties.
const float abs_angle = atan2f(fabsf(m_target_point_lc.x()),
fabsf(m_target_point_lc.z()));
if ((m_cur_difficulty == RaceManager::DIFFICULTY_HARD ||
@ -636,7 +655,7 @@ void ArenaAI::doSkiddingTest()
/** Determine if the path to target needs to be changed to avoid bad items, it
* will also set the turn radius based on the new path if necessary.
* \param forward Forward node of current AI position.
* \param path Default path to target.
* \param[in,out] path Default path to follow, will be changed if needed.
*/
void ArenaAI::determinePath(int forward, std::vector<int>* path)
{

View File

@ -32,7 +32,6 @@ class ArenaGraph;
namespace irr
{
namespace scene { class ISceneNode; }
namespace video { class ITexture; }
}
/** A base class for AI that use navmesh to work.
@ -41,12 +40,16 @@ namespace irr
class ArenaAI : public AIBaseController
{
protected:
/** Pointer to the \ref ArenaGraph. */
ArenaGraph* m_graph;
/** Pointer to the closest kart around this kart. */
AbstractKart *m_closest_kart;
/** The \ref ArenaNode at which the closest kart located on. */
int m_closest_kart_node;
/** The closest kart location. */
Vec3 m_closest_kart_point;
/** Holds the current difficulty. */
@ -55,25 +58,39 @@ protected:
/** For debugging purpose: a sphere indicating where the AI
* is targeting at. */
irr::scene::ISceneNode *m_debug_sphere;
/** For debugging purpose: a sphere indicating where the first
* turning corner is located. */
irr::scene::ISceneNode *m_debug_sphere_next;
/** The node(quad) at which the target point lies in. */
/** The \ref ArenaNode at which the target point located on. */
int m_target_node;
/** The target point. */
/** The coordinates of target point. */
Vec3 m_target_point;
/** True if AI can skid, currently only do when close to target, see
* \ref doSkiddingTest(). */
bool m_mini_skid;
void collectItemInArena(Vec3*, int*) const;
virtual void findClosestKart(bool use_difficulty, bool find_sta) = 0;
// ------------------------------------------------------------------------
void tryCollectItem(Vec3* aim_point, int* target_node) const;
// ------------------------------------------------------------------------
/** Find the closest kart around this AI, implemented by sub-class.
* \param consider_difficulty If take current difficulty into account.
* \param find_sta If find \ref SpareTireAI only. */
virtual void findClosestKart(bool consider_difficulty, bool find_sta) = 0;
private:
/** Local coordinates of current target point. */
Vec3 m_target_point_lc;
/** Save the last target point before reversing, so AI will end reversing
* until facing in front of it. */
Vec3 m_reverse_point;
/** Indicates that the kart is currently stuck, and m_time_since_reversing is
* counting down. */
/** Indicates that the kart is currently stuck, and m_time_since_reversing
* is counting down. */
bool m_is_stuck;
/** Indicates that the kart need a uturn to reach a node behind, and
@ -99,39 +116,79 @@ private:
/** This is a timer that counts when the kart start going off road. */
float m_time_since_off_road;
/** Used to determine braking and nitro usage. */
float m_turn_radius;
/** Used to determine if skidding can be done. */
float m_steering_angle;
/** The point in front of the AI which distance is \ref m_kart_length, used
* to compensate the time difference between steering when finding next
* node. */
Vec3 m_current_forward_point;
/** The \ref ArenaNode at which the forward point located on. */
int m_current_forward_node;
void configSpeed();
// ------------------------------------------------------------------------
void configSteering();
// ------------------------------------------------------------------------
void checkIfStuck(const float dt);
// ------------------------------------------------------------------------
void determinePath(int forward, std::vector<int>* path);
// ------------------------------------------------------------------------
void doSkiddingTest();
// ------------------------------------------------------------------------
void doUTurn(const float dt);
// ------------------------------------------------------------------------
bool gettingUnstuck(const float dt);
// ------------------------------------------------------------------------
bool updateAimingPosition(Vec3* target_point);
// ------------------------------------------------------------------------
void useItems(const float dt);
// ------------------------------------------------------------------------
virtual bool canSkid(float steer_fraction) OVERRIDE
{ return m_mini_skid; }
{ return m_mini_skid; }
// ------------------------------------------------------------------------
/** Find a suitable target for this frame, implemented by sub-class. */
virtual void findTarget() = 0;
virtual bool forceBraking() { return false; }
// ------------------------------------------------------------------------
/** If true, AI will always try to brake for this frame. */
virtual bool forceBraking() { return false; }
// ------------------------------------------------------------------------
/** Return the current \ref ArenaNode the AI located on. */
virtual int getCurrentNode() const = 0;
// ------------------------------------------------------------------------
/** Return the distance based on graph distance matrix to any kart.
* \param kart \ref AbstractKart to check. */
virtual float getKartDistance(const AbstractKart* kart) const = 0;
virtual bool ignorePathFinding() { return false; }
// ------------------------------------------------------------------------
/** If true, AI will drive directly to target without path finding. */
virtual bool ignorePathFinding() { return false; }
// ------------------------------------------------------------------------
/** If true, AI will stop moving. */
virtual bool isWaiting() const = 0;
// ------------------------------------------------------------------------
/** If true, AI stays on the \ref ArenaNode correctly, otherwise
* \ref RescueAnimation will be done after sometime. */
virtual bool isKartOnRoad() const = 0;
virtual void resetAfterStop() {};
// ------------------------------------------------------------------------
/** Overridden if any action is needed to be done when AI stopped
* moving or changed driving direction. */
virtual void resetAfterStop() {}
public:
ArenaAI(AbstractKart *kart);
virtual ~ArenaAI() {};
// ------------------------------------------------------------------------
virtual ~ArenaAI() {}
// ------------------------------------------------------------------------
virtual void update (float delta) OVERRIDE;
// ------------------------------------------------------------------------
virtual void reset () OVERRIDE;
// ------------------------------------------------------------------------
virtual void newLap (int lap) OVERRIDE {}
};
#endif

View File

@ -56,7 +56,6 @@ BattleAI::BattleAI(AbstractKart *kart)
} // BattleAI
//-----------------------------------------------------------------------------
BattleAI::~BattleAI()
{
#ifdef AI_DEBUG
@ -66,7 +65,12 @@ BattleAI::~BattleAI()
} // ~BattleAI
//-----------------------------------------------------------------------------
void BattleAI::findClosestKart(bool use_difficulty, bool find_sta)
/** Find the closest kart around this AI, if consider_difficulty is true, AI
* will try to follow human players more or less depends on difficulty.
* \param consider_difficulty If take current difficulty into account.
* \param find_sta If find \ref SpareTireAI only.
*/
void BattleAI::findClosestKart(bool consider_difficulty, bool find_sta)
{
float distance = 99999.9f;
int closest_kart_num = 0;
@ -88,7 +92,8 @@ void BattleAI::findClosestKart(bool use_difficulty, bool find_sta)
// Test whether takes current difficulty into account for closest kart
// Notice: it don't affect aiming, this function will be called once
// more when use items, which ignore difficulty.
if (m_cur_difficulty == RaceManager::DIFFICULTY_EASY && use_difficulty)
if (m_cur_difficulty == RaceManager::DIFFICULTY_EASY &&
consider_difficulty)
{
// Skip human players for novice mode unless only they are left
const AbstractKart* temp = m_world->getKart(start_id);
@ -98,7 +103,7 @@ void BattleAI::findClosestKart(bool use_difficulty, bool find_sta)
continue;
}
else if (m_cur_difficulty == RaceManager::DIFFICULTY_BEST &&
use_difficulty)
consider_difficulty)
{
// Skip AI players for supertux mode
const AbstractKart* temp = m_world->getKart(start_id);
@ -122,33 +127,44 @@ void BattleAI::findClosestKart(bool use_difficulty, bool find_sta)
} // findClosestKart
//-----------------------------------------------------------------------------
/** Find a suitable target to follow, it will find the closest kart first, it's
* used as fallback if no item is found. It takes the current difficulty into
* account, also collect life from \ref SpareTireAI depends on current
* difficulty if actually they are spawned:
* \li Novice and intermediate - collect them only AI has 1 life only.
* \li Expert and supertux - collect them if AI dones't have 3 lives.
*/
void BattleAI::findTarget()
{
// Find the closest kart first, it's used as fallback if no item is found.
// It takes the current difficulty into account, also collect life from
// spare tire karts when neccessary
bool find_sta = false;
if (m_world->spareTireKartsSpawned())
{
switch (m_cur_difficulty)
{
case RaceManager::DIFFICULTY_EASY:
case RaceManager::DIFFICULTY_MEDIUM:
{
find_sta = m_world->getKartLife(m_kart->getWorldKartId()) == 1;
break;
}
case RaceManager::DIFFICULTY_HARD:
case RaceManager::DIFFICULTY_BEST:
{
find_sta = m_world->getKartLife(m_kart->getWorldKartId()) != 3;
break;
}
default: assert(false);
}
}
// Collect life depends on current difficulty:
// Novice and intermediate - collect them only AI has 1 life only
// Expert and supertux - collect them if AI dones't have 3 lives
// Also when actually spare tire karts are spawned
bool find_sta = m_world->spareTireKartsSpawned() ?
((m_cur_difficulty == RaceManager::DIFFICULTY_EASY ||
m_cur_difficulty == RaceManager::DIFFICULTY_MEDIUM) &&
m_world->getKartLife(m_kart->getWorldKartId()) == 1 ?
true :
(m_cur_difficulty == RaceManager::DIFFICULTY_HARD ||
m_cur_difficulty == RaceManager::DIFFICULTY_BEST) &&
m_world->getKartLife(m_kart->getWorldKartId()) != 3 ?
true : false) : false;
findClosestKart(find_sta ? false : true/*use_difficulty*/, find_sta);
bool consider_difficulty = !find_sta;
findClosestKart(consider_difficulty, find_sta);
// Find a suitable target to drive to, either powerup or kart
if (m_kart->getPowerup()->getType() == PowerupManager::POWERUP_NOTHING &&
m_kart->getAttachment()->getType() != Attachment::ATTACH_SWATTER &&
!find_sta)
collectItemInArena(&m_target_point , &m_target_node);
tryCollectItem(&m_target_point , &m_target_node);
else
{
m_target_point = m_closest_kart_point;

View File

@ -33,16 +33,28 @@ class BattleAI : public ArenaAI
protected:
/** Keep a pointer to world. */
ThreeStrikesBattle *m_world;
virtual void findClosestKart(bool use_difficulty, bool find_sta) OVERRIDE;
// ------------------------------------------------------------------------
virtual void findClosestKart(bool consider_difficulty,
bool find_sta) OVERRIDE;
// ------------------------------------------------------------------------
virtual int getCurrentNode() const OVERRIDE;
private:
// ------------------------------------------------------------------------
virtual void findTarget() OVERRIDE;
// ------------------------------------------------------------------------
virtual float getKartDistance(const AbstractKart* kart) const OVERRIDE;
// ------------------------------------------------------------------------
virtual bool isKartOnRoad() const OVERRIDE;
// ------------------------------------------------------------------------
virtual bool isWaiting() const OVERRIDE;
public:
BattleAI(AbstractKart *kart);
// ------------------------------------------------------------------------
~BattleAI();
};
#endif

View File

@ -129,7 +129,7 @@ void SoccerAI::update(float dt)
} // update
//-----------------------------------------------------------------------------
void SoccerAI::findClosestKart(bool use_difficulty, bool find_sta)
void SoccerAI::findClosestKart(bool consider_difficulty, bool find_sta)
{
float distance = 99999.9f;
const unsigned int n = m_world->getNumKarts();
@ -165,7 +165,7 @@ void SoccerAI::findClosestKart(bool use_difficulty, bool find_sta)
//-----------------------------------------------------------------------------
void SoccerAI::findTarget()
{
findClosestKart(true/*use_difficulty*/, false/*find_sta*/);
findClosestKart(true/*consider_difficulty*/, false/*find_sta*/);
// Check if this AI kart is the one who will chase the ball
if (m_world->getBallChaser(m_cur_team) == (signed)m_kart->getWorldKartId())
{
@ -181,7 +181,7 @@ void SoccerAI::findTarget()
if (m_kart->getPowerup()->getType() == PowerupManager::POWERUP_NOTHING &&
m_kart->getAttachment()->getType() != Attachment::ATTACH_SWATTER)
{
collectItemInArena(&m_target_point , &m_target_node);
tryCollectItem(&m_target_point , &m_target_node);
}
else if (m_world->getAttacker(m_cur_team) == (signed)m_kart
->getWorldKartId())

View File

@ -65,7 +65,7 @@ private:
virtual bool canSkid(float steer_fraction) OVERRIDE
{ return m_mini_skid && !(m_overtake_ball || m_chasing_ball); }
virtual void findClosestKart(bool use_difficulty, bool find_sta) OVERRIDE;
virtual void findClosestKart(bool consider_difficulty, bool find_sta) OVERRIDE;
virtual void findTarget() OVERRIDE;
virtual bool forceBraking() OVERRIDE { return m_force_brake; }
virtual int getCurrentNode() const OVERRIDE;