1) Fixed auto-rescue of AI kart if they are stuck.
Now a certain number of unique collisions in a certain amount of time triggers auto rescue (3 rescues in 3 seconds). This should fix #576. The old handling is still left in place (in case that some other rescues are better caught by that code). 2) Removed unused m_collided variable (and related stuff). 3) Fixed the 'crashed' callback functions in the controller (which didn't work anymore, since parameters were changed: kart called crash(), but the AI controller only had crashed(Kart*), so the empty dummy function in controller was called). 4) Made nearly all virtual functions in Controller pure, so that problems similar to 3) are hopefully picked up at compile time. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@11011 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
parent
d77fc80e09
commit
53b4b7d47c
@ -55,6 +55,13 @@ AIBaseController::AIBaseController(AbstractKart *kart,
|
||||
|
||||
} // AIBaseController
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void AIBaseController::reset()
|
||||
{
|
||||
m_stuck_trigger_rescue = false;
|
||||
m_collision_times.clear();
|
||||
} // reset
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Triggers a recomputation of the path to use, so that the AI does not
|
||||
* always use the same way.
|
||||
@ -122,10 +129,16 @@ void AIBaseController::computePath()
|
||||
m_all_look_aheads[i] = l;
|
||||
}
|
||||
} // computePath
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Updates the ai base controller each time step. Note that any calls to
|
||||
* isStuck() must be done before update is called, since update will reset
|
||||
* the isStuck flag!
|
||||
* \param dt Time step size.
|
||||
*/
|
||||
void AIBaseController::update(float dt)
|
||||
{
|
||||
Controller::update(dt);
|
||||
m_stuck_trigger_rescue = false;
|
||||
|
||||
if(QuadGraph::get())
|
||||
{
|
||||
@ -150,6 +163,65 @@ void AIBaseController::update(float dt)
|
||||
}
|
||||
} // update
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** 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
|
||||
* of collisions happened in a certain amount of time, and if so rescues
|
||||
* the kart.
|
||||
* \paran m Pointer to the material that was hit (NULL if no specific
|
||||
* material was used for the part of the track that was hit).
|
||||
*/
|
||||
void AIBaseController::crashed(const Material *m)
|
||||
{
|
||||
// Defines how many collision in what time will trigger a rescue.
|
||||
// Note that typically it takes ~0.5 seconds for the AI to hit
|
||||
// the track again if it is stuck (i.e. time for the push back plus
|
||||
// time for the AI to accelerate and hit the terrain again).
|
||||
const int NUM_COLLISION = 3;
|
||||
const float COLLISION_TIME = 1.5f;
|
||||
|
||||
float time = m_world->getTime();
|
||||
if(m_collision_times.size()==0)
|
||||
{
|
||||
m_collision_times.push_back(time);
|
||||
return;
|
||||
}
|
||||
|
||||
// Filter out multiple collisions report caused by single collision
|
||||
// (bullet can report a collision more than once per frame, and
|
||||
// resolving it can take a few frames as well, causing more reported
|
||||
// collisions to happen). The time of 0.2 seconds was experimentally
|
||||
// found, typically it takes 0.5 seconds for a kart to be pushed back
|
||||
// from the terrain and accelerate to hit the same terrain again.
|
||||
if(time - m_collision_times.back() < 0.2f)
|
||||
return;
|
||||
|
||||
|
||||
// Remove all outdated entries, i.e. entries that are older than the
|
||||
// collision time plus 1 second. Older entries must be deleted,
|
||||
// otherwise a collision that happened (say) 10 seconds ago could
|
||||
// contribute to a stuck condition.
|
||||
while(m_collision_times.size()>0 &&
|
||||
time - m_collision_times[0] > 1.0f+COLLISION_TIME)
|
||||
m_collision_times.erase(m_collision_times.begin());
|
||||
|
||||
m_collision_times.push_back(time);
|
||||
|
||||
// Now detect if there are enough collision records in the
|
||||
// specified time interval.
|
||||
if(time - m_collision_times.front() > COLLISION_TIME
|
||||
&& m_collision_times.size()>=NUM_COLLISION)
|
||||
{
|
||||
// We can't call m_kart->forceRescue here, since crased() is
|
||||
// called during physics processing, and forceRescue() removes the
|
||||
// chassis from the physics world, which would then cause
|
||||
// inconsistencies and potentially a crash during the physics
|
||||
// processing. So only set a flag, which is tested during update.
|
||||
m_stuck_trigger_rescue = true;
|
||||
}
|
||||
|
||||
} // crashed(Material)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Returns the next sector of the given sector index. This is used
|
||||
* for branches in the quad graph to select which way the AI kart should
|
||||
|
@ -38,6 +38,16 @@ private:
|
||||
* different AI levels.
|
||||
*/
|
||||
float m_skidding_threshold;
|
||||
|
||||
/** Stores the last N times when a collision happened. This is used
|
||||
* to detect when the AI is stuck, i.e. N collisions happened in
|
||||
* a certain period of time. */
|
||||
std::vector<float> m_collision_times;
|
||||
|
||||
/** A flag that is set during the physics processing to indicate that
|
||||
* this kart is stuck and needs to be rescued. */
|
||||
bool m_stuck_trigger_rescue;
|
||||
|
||||
protected:
|
||||
/** Length of the kart, storing it here saves many function calls. */
|
||||
float m_kart_length;
|
||||
@ -78,12 +88,29 @@ protected:
|
||||
void setSteering (float angle, float dt);
|
||||
void setSkiddingFraction(float f);
|
||||
void computePath();
|
||||
// ------------------------------------------------------------------------
|
||||
/** 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_trigger_rescue; }
|
||||
|
||||
public:
|
||||
AIBaseController(AbstractKart *kart,
|
||||
StateManager::ActivePlayer *player=NULL);
|
||||
virtual ~AIBaseController() {};
|
||||
};
|
||||
virtual void reset();
|
||||
virtual void crashed(const AbstractKart *k) {};
|
||||
virtual void crashed(const Material *m);
|
||||
virtual void handleZipper(bool play_sound) {};
|
||||
virtual void finishedRace(float time) {};
|
||||
virtual void collectedItem(const Item &item, int add_info=-1,
|
||||
float previous_energy=0) {};
|
||||
virtual void setPosition(int p) {};
|
||||
virtual bool isNetworkController() const { return false; }
|
||||
virtual bool isPlayerController() const { return false; }
|
||||
virtual void action(PlayerAction action, int value) {};
|
||||
virtual void skidBonusTriggered() {};
|
||||
|
||||
}; // AIBaseController
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2010 Joerg Henrichs
|
||||
@ -34,6 +35,7 @@ using namespace irr;
|
||||
class AbstractKart;
|
||||
class Item;
|
||||
class KartControl;
|
||||
class Material;
|
||||
|
||||
/** This is the base class for kart controller - that can be a player
|
||||
* or a a robot.
|
||||
@ -56,33 +58,36 @@ public:
|
||||
Controller (AbstractKart *kart,
|
||||
StateManager::ActivePlayer *player=NULL);
|
||||
virtual ~Controller () {};
|
||||
virtual void reset () = 0;
|
||||
virtual void update (float dt) = 0;
|
||||
virtual void handleZipper (bool play_sound) = 0;
|
||||
virtual void collectedItem (const Item &item, int add_info=-1,
|
||||
float previous_energy=0) = 0;
|
||||
virtual void crashed (const AbstractKart *k) = 0;
|
||||
virtual void crashed (const Material *m) = 0;
|
||||
virtual void setPosition (int p) = 0;
|
||||
virtual void finishedRace (float time) = 0;
|
||||
virtual bool isPlayerController () const = 0;
|
||||
virtual bool isNetworkController() const = 0;
|
||||
virtual const irr::core::stringw& getNamePostfix() const;
|
||||
// ---------------------------------------------------------------------------
|
||||
/** Returns the active player for this controller (NULL
|
||||
* if this controller does not belong to a player. */
|
||||
StateManager::ActivePlayer *getPlayer () {return m_player;}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** Returns the player object (or NULL if it's a computer controller). */
|
||||
const StateManager::ActivePlayer *getPlayer () const { return m_player; }
|
||||
|
||||
virtual void reset () {};
|
||||
virtual void update (float dt) {};
|
||||
virtual void handleZipper (bool play_sound) {};
|
||||
virtual void collectedItem (const Item &item, int add_info=-1,
|
||||
float previous_energy=0) {};
|
||||
|
||||
virtual void crashed () {};
|
||||
virtual void setPosition (int p) {};
|
||||
virtual void finishedRace (float time) {};
|
||||
virtual bool isPlayerController () const {return false;}
|
||||
virtual bool isNetworkController() const {return false;}
|
||||
virtual const irr::core::stringw& getNamePostfix() const;
|
||||
// ------------------------------------------------------------------------
|
||||
/** Default: ignore actions. Only PlayerController get them. */
|
||||
virtual void action (PlayerAction action, int value) {}
|
||||
virtual void action(PlayerAction action, int value) = 0;
|
||||
// ------------------------------------------------------------------------
|
||||
/** Callback whenever a new lap is triggered. Used by the AI
|
||||
* to trigger a recomputation of the way to use. */
|
||||
virtual void newLap (int lap) {}
|
||||
virtual void newLap(int lap) = 0;
|
||||
// ------------------------------------------------------------------------
|
||||
virtual void skidBonusTriggered() {}
|
||||
virtual void skidBonusTriggered() = 0;
|
||||
}; // Controller
|
||||
|
||||
#endif
|
||||
|
@ -127,8 +127,6 @@ void DefaultAIController::reset()
|
||||
m_curve_target_speed = m_kart->getCurrentMaxSpeed();
|
||||
m_curve_angle = 0.0;
|
||||
m_start_delay = -1.0f;
|
||||
m_crash_time = 0.0f;
|
||||
m_collided = false;
|
||||
m_time_since_stuck = 0.0f;
|
||||
m_kart_ahead = NULL;
|
||||
m_distance_ahead = 0.0f;
|
||||
@ -147,6 +145,7 @@ void DefaultAIController::reset()
|
||||
m_track_node = QuadGraph::get()->findOutOfRoadSector(m_kart->getXYZ());
|
||||
}
|
||||
|
||||
AIBaseController::reset();
|
||||
} // reset
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -192,6 +191,14 @@ void DefaultAIController::update(float dt)
|
||||
return;
|
||||
}
|
||||
|
||||
// If the kart needs to be rescued, do it now (and nothing else)
|
||||
if(isStuck())
|
||||
{
|
||||
m_kart->forceRescue();
|
||||
AIBaseController::update(dt);
|
||||
return;
|
||||
}
|
||||
|
||||
if( m_world->isStartPhase() )
|
||||
{
|
||||
handleRaceStart();
|
||||
@ -270,7 +277,6 @@ void DefaultAIController::update(float dt)
|
||||
|
||||
/*And obviously general kart stuff*/
|
||||
AIBaseController::update(dt);
|
||||
m_collided = false;
|
||||
m_controls->m_fire = false;
|
||||
} // update
|
||||
|
||||
@ -374,12 +380,14 @@ void DefaultAIController::handleSteering(float dt)
|
||||
// that the kart is off track. In this case, steer so that the kart
|
||||
// will rotate towards the center of the track. E.g. if the kart is
|
||||
// to the right, steer towards the right.
|
||||
#ifdef XX
|
||||
if(m_kart->getSpeed()<0)
|
||||
{
|
||||
steer_angle = side_dist > 0 ? -m_kart->getMaxSteerAngle()
|
||||
: m_kart->getMaxSteerAngle();
|
||||
}
|
||||
else
|
||||
#endif
|
||||
steer_angle = steerToPoint(QuadGraph::get()->getQuadOfNode(next)
|
||||
.getCenter());
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2004-2005 Steve Baker <sjbaker1@airmail.net>
|
||||
@ -93,20 +94,18 @@ private:
|
||||
bool m_make_use_of_slipstream;
|
||||
|
||||
/*General purpose variables*/
|
||||
//The crash percentage is how much of the time the AI has been crashing,
|
||||
//if the AI has been crashing for some time, use the rescue.
|
||||
float m_crash_time;
|
||||
int m_collided; // true if the kart collided with the track
|
||||
|
||||
/** Pointer to the closest kart ahead of this kart. NULL if this
|
||||
* kart is first. */
|
||||
AbstractKart *m_kart_ahead;
|
||||
|
||||
/** Distance to the kart ahead. */
|
||||
float m_distance_ahead;
|
||||
|
||||
/** Pointer to the closest kart behind this kart. NULL if this kart
|
||||
* is last. */
|
||||
AbstractKart *m_kart_behind;
|
||||
|
||||
/** Distance to the kard behind. */
|
||||
float m_distance_behind;
|
||||
|
||||
@ -151,7 +150,6 @@ public:
|
||||
~DefaultAIController();
|
||||
virtual void update (float delta) ;
|
||||
virtual void reset ();
|
||||
virtual void crashed (AbstractKart *k) {if(k) m_collided = true;};
|
||||
virtual const irr::core::stringw& getNamePostfix() const;
|
||||
};
|
||||
|
||||
|
@ -208,7 +208,6 @@ void NewAIController::update(float dt)
|
||||
m_controls->m_fire = true;
|
||||
}
|
||||
}
|
||||
m_collided = false;
|
||||
} // update
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -823,7 +822,6 @@ void NewAIController::reset()
|
||||
m_curve_angle = 0.0;
|
||||
m_time_till_start = -1.0f;
|
||||
m_crash_time = 0.0f;
|
||||
m_collided = false;
|
||||
m_time_since_stuck = 0.0f;
|
||||
m_kart_ahead = NULL;
|
||||
m_distance_ahead = 0.0f;
|
||||
|
@ -85,7 +85,6 @@ private:
|
||||
//The crash percentage is how much of the time the AI has been crashing,
|
||||
//if the AI has been crashing for some time, use the rescue.
|
||||
float m_crash_time;
|
||||
int m_collided; // true if the kart collided with the track
|
||||
|
||||
/** Pointer to the closest kart ahead of this kart. NULL if this
|
||||
* kart is first. */
|
||||
@ -148,7 +147,6 @@ public:
|
||||
virtual ~NewAIController();
|
||||
virtual void update (float delta) ;
|
||||
virtual void reset ();
|
||||
virtual void crashed (AbstractKart *k) {if(k) m_collided = true;};
|
||||
virtual const irr::core::stringw& getN() const
|
||||
{
|
||||
static irr::core::stringw name("(NewAI)");
|
||||
|
@ -86,7 +86,6 @@ void PlayerController::reset()
|
||||
m_prev_brake = 0;
|
||||
m_prev_accel = 0;
|
||||
m_penalty_time = 0;
|
||||
Controller::reset();
|
||||
} // reset
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -320,13 +319,6 @@ void PlayerController::update(float dt)
|
||||
m_controls->m_accel = 0.0f;
|
||||
|
||||
} // if key pressed
|
||||
else
|
||||
{
|
||||
// The call to update is necessary here (even though the kart
|
||||
// shouldn't actually change) to update m_transform. Otherwise
|
||||
// the camera gets the wrong position.
|
||||
Controller::update(dt);
|
||||
}
|
||||
return;
|
||||
} // if isStartPhase
|
||||
|
||||
@ -371,7 +363,6 @@ void PlayerController::update(float dt)
|
||||
{
|
||||
m_bzzt_sound->play();
|
||||
}
|
||||
Controller::update(dt);
|
||||
} // update
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -62,9 +62,16 @@ public:
|
||||
virtual void skidBonusTriggered();
|
||||
virtual void setPosition (int p);
|
||||
virtual void finishedRace (float time);
|
||||
bool isPlayerController() const {return true;}
|
||||
virtual bool isPlayerController() const {return true;}
|
||||
virtual bool isNetworkController() const { return false; }
|
||||
virtual void reset ();
|
||||
void resetInputState ();
|
||||
virtual void crashed (const AbstractKart *k) {}
|
||||
virtual void crashed (const Material *m) {}
|
||||
// ------------------------------------------------------------------------
|
||||
/** Callback whenever a new lap is triggered. Used by the AI
|
||||
* to trigger a recomputation of the way to use. */
|
||||
virtual void newLap(int lap) {}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1498,6 +1498,7 @@ void Kart::crashed(AbstractKart *k, bool update_attachments)
|
||||
assert(k);
|
||||
getAttachment()->handleCollisionWithKart(k);
|
||||
}
|
||||
m_controller->crashed(k);
|
||||
crashed();
|
||||
} // crashed(Kart, update_attachments
|
||||
|
||||
@ -1598,7 +1599,7 @@ void Kart::crashed(const Material *m)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_controller->crashed(m);
|
||||
crashed();
|
||||
} // crashed(Material)
|
||||
|
||||
@ -1607,8 +1608,6 @@ void Kart::crashed(const Material *m)
|
||||
*/
|
||||
void Kart::crashed()
|
||||
{
|
||||
m_controller->crashed();
|
||||
|
||||
if(World::getWorld()->getTime()-m_time_last_crash < 0.5f) return;
|
||||
|
||||
m_time_last_crash = World::getWorld()->getTime();
|
||||
|
Loading…
Reference in New Issue
Block a user