1) Changed the minimum turn radius when skidding to be 20% instead

of 40%. This allows longer skids in wider turns (e.g. hacienda).
2) Improved skidding decision when sharp turning is required:
   on sharp turn when already skidding, wait till an 'even sharper'
   turn is required, which (usually) means that then the AI is
   nicely aligned with the new track direction when releasing skid,
   which makes nice use of the bonus and the additional rotation.
   If not skidding when sharp turn is required, don't even start
   one.
3) Prevent AI from skidding 'against' track direction (i.e. track
   is turning left, but AI tries to skid right). This happened
   before (e.g. when slightly adjusting steering) and caused
   rapid left/right turns (and skid/stop/skid/stop sequences).
4) Allow some steering in wrong direction when skidding (to allow
   for some incorrect estimations, and to avoid skidding on/off
   sequences when only minor corrections are necessary).
5) If adjusted (i.e. taking the skid steering reduction into account)
   steer fraction when skidding is too high, stop skidding.
6) Re-enabled braking when AI is not aligned with track direction.
7) Improve debug output so that only a state change (skidding to
   non-skidding and vice versa) triggers output (instead of output
   every frame).


git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@11469 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk
2012-08-05 23:27:39 +00:00
parent 21c26f5f54
commit 13175b8566
2 changed files with 85 additions and 13 deletions

View File

@@ -196,7 +196,7 @@
bonus-speed="4.5 6.5" bonus-time="3.0 4.0"
bonus-force="250 350"
post-skid-rotate-factor="1" jump-time="0.4"
reduce-turn-min="0.4" reduce-turn-max="0.8"/>
reduce-turn-min="0.2" reduce-turn-max="0.8"/>
<!-- Slipstream: length: How far behind a kart slipstream works
collect-time: How many seconds of sstream give maximum benefit

View File

@@ -358,9 +358,9 @@ void SkiddingAI::handleBraking()
#ifdef DEBUG
if(m_ai_debug)
printf("[AI] braking: %s not aligned with track.\n",
m_kart->getIdent().c_str());
m_kart->getIdent().c_str());
#endif
//m_controls->m_brake = true;
m_controls->m_brake = true;
return;
}
if(m_current_track_direction==GraphNode::DIR_LEFT ||
@@ -1226,7 +1226,6 @@ void SkiddingAI::determineTrackDirection()
m_curve[CURVE_QG]->addPoint(qg->getNode(i).getCenter());
}
#endif
m_controls->m_skid = false;
if(m_current_track_direction==GraphNode::DIR_LEFT ||
m_current_track_direction==GraphNode::DIR_RIGHT )
@@ -1262,7 +1261,10 @@ void SkiddingAI::handleCurve()
determineTurnRadius(xyz, tangent, last_xyz,
&m_curve_center, &m_current_curve_radius);
#undef ADJUST_TURN_RADIUS_TO_AVOID_CRASH_INTO_TRACK
#ifdef ADJUST_TURN_RADIUS_TO_AVOID_CRASH_INTO_TRACK
// NOTE: this can deadlock if the AI is going on a shortcut, since
// m_last_direction_node is based on going on the main driveline :(
unsigned int i= m_track_node;
while(1)
{
@@ -1276,7 +1278,8 @@ void SkiddingAI::handleCurve()
last_xyz = qg->getQuadOfNode(i)[index];
determineTurnRadius(xyz, tangent, last_xyz,
&m_curve_center, &m_current_curve_radius);
//m_current_curve_radius = r;
m_current_curve_radius = r;
m_last_direction_node = i;
break;
}
if(i==m_last_direction_node)
@@ -1301,9 +1304,42 @@ void SkiddingAI::handleCurve()
*/
bool SkiddingAI::doSkid(float steer_fraction)
{
if(fabsf(steer_fraction)>1.5f)
{
// If the kart has to do a sharp turn, but is already skidding, find
// a good time to release the skid button, since this will turn the
// kart more sharply:
if(m_controls->m_skid)
{
#ifdef DEBUG
if(m_ai_debug)
{
if(fabsf(steer_fraction)>=2.5f)
printf("[AI] skid: %s stops skidding (%f).\n",
m_kart->getIdent().c_str(), steer_fraction);
}
#endif
// If the current turn is not sharp enough, delay releasing
// the skid button.
return fabsf(steer_fraction)<2.5f;
}
// If the kart is not skidding, now is not a good time to start
return false;
}
// No skidding on straights
if(m_current_track_direction==GraphNode::DIR_STRAIGHT)
{
#ifdef DEBUG
if(m_controls->m_skid && m_ai_debug)
{
printf("[AI] skid: %s stops skidding on straight.\n",
m_kart->getIdent().c_str());
}
#endif
return false;
}
const float MIN_SKID_SPEED = 5.0f;
const QuadGraph *qg = QuadGraph::get();
@@ -1323,8 +1359,15 @@ bool SkiddingAI::doSkid(float steer_fraction)
angle = normalizeAngle(angle);
float length = m_current_curve_radius*fabsf(angle);
float duration = length / m_kart->getSpeed();
// The estimated skdding time is usually too short - partly because
// he speed of the kart decreases during the turn, partly because
// the actual path is adjusted during the turn. So apply an
// experimentally found factor in to get better estimates.
duration *= 1.5f;
const Skidding *skidding = m_kart->getSkidding();
// If the remaining estimated time for skidding is too short, stop
// it. This code will mostly trigger the bonus at the end of a skid.
if(m_controls->m_skid && duration < 1.0f)
{
if(m_ai_debug)
@@ -1332,12 +1375,28 @@ bool SkiddingAI::doSkid(float steer_fraction)
m_kart->getIdent().c_str());
return false;
}
// Test if the AI is trying to skid against track direction. This
// can happen if the AI is adjusting steering somewhat (e.g. in a
// left turn steer right to avoid getting too close to the left
// vorder). In this case skidding will be useless.
else if( (steer_fraction > 0 &&
m_current_track_direction==GraphNode::DIR_LEFT) ||
(steer_fraction < 0 &&
m_current_track_direction==GraphNode::DIR_RIGHT) )
{
#ifdef DEBUG
if(m_controls->m_skid && m_ai_debug)
printf("[AI] skid: %s skidding against track direction.\n",
m_kart->getIdent().c_str());
#endif
return false;
}
// If there is a skidding bonus, try to get it.
else if(skidding->getNumberOfBonusTimes()>0 &&
skidding->getTimeTillBonus(0) < duration)
skidding->getTimeTillBonus(0) < duration)
{
#ifdef DEBUG
if(m_ai_debug)
if(!m_controls->m_skid && m_ai_debug)
printf("[AI] skid: %s start skid, duration %f.\n",
m_kart->getIdent().c_str(), duration);
#endif
@@ -1345,6 +1404,11 @@ bool SkiddingAI::doSkid(float steer_fraction)
} // if curve long enough for skidding
#ifdef DEBUG
if(m_controls->m_skid && m_ai_debug)
printf("[AI] skid: %s has no reasons to skid anymore.\n",
m_kart->getIdent().c_str());
#endif
return false;
} // doSkid
@@ -1385,8 +1449,8 @@ void SkiddingAI::setSteering(float angle, float dt)
// we can't turn into the direction we want to anymore (see
// Skidding class)
Skidding::SkidState ss = skidding->getSkidState();
if(ss==Skidding::SKID_ACCUMULATE_LEFT && steer_fraction>0 ||
ss==Skidding::SKID_ACCUMULATE_RIGHT && steer_fraction<0 )
if(ss==Skidding::SKID_ACCUMULATE_LEFT && steer_fraction>0.2f ||
ss==Skidding::SKID_ACCUMULATE_RIGHT && steer_fraction<-0.2f )
{
m_controls->m_skid = false;
#ifdef DEBUG
@@ -1396,12 +1460,20 @@ void SkiddingAI::setSteering(float angle, float dt)
#endif
}
if(m_controls->m_skid && (
skidding->getSkidState()==Skidding::SKID_ACCUMULATE_LEFT ||
skidding->getSkidState()==Skidding::SKID_ACCUMULATE_RIGHT))
if(m_controls->m_skid && ( ss==Skidding::SKID_ACCUMULATE_LEFT ||
ss==Skidding::SKID_ACCUMULATE_RIGHT ) )
{
steer_fraction =
skidding->getSteeringWhenSkidding(steer_fraction);
if(fabsf(steer_fraction)>1.8)
{
#ifdef DEBUG
if(m_ai_debug)
printf("[AI] skid: %s steering too much (%f).\n",
m_kart->getIdent().c_str(), steer_fraction);
#endif
m_controls->m_skid = false;
}
if(steer_fraction<-1.0f)
steer_fraction = -1.0f;
else if(steer_fraction>1.0f)