Improved AI to remove most of the 'shaking'.

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/trunk/supertuxkart@2600 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk
2008-12-10 04:40:51 +00:00
parent 6fff45d103
commit 4c3ff0c87d
4 changed files with 71 additions and 29 deletions

View File

@@ -59,7 +59,7 @@ KartProperties::KartProperties() : m_icon_material(0)
m_max_speed_turn = m_angle_at_max = m_engine_power = m_brake_factor =
m_time_full_steer = m_wheelie_max_pitch = m_wheelie_max_speed_ratio =
m_wheelie_pitch_rate = m_wheelie_restore_rate = m_wheelie_speed_boost =
m_suspension_stiffness = m_wheel_damping_relaxation =
m_suspension_stiffness = m_wheel_damping_relaxation = m_wheel_base =
m_wheel_damping_compression = m_friction_slip = m_roll_influence =
m_wheel_radius = m_wheelie_power_boost = m_chassis_linear_damping =
m_chassis_angular_damping = m_maximum_speed = m_suspension_rest =
@@ -68,7 +68,7 @@ KartProperties::KartProperties() : m_icon_material(0)
m_track_connection_accel = m_min_speed_turn = m_angle_at_min =
m_max_speed_turn = m_angle_at_max =
m_rubber_band_max_length = m_rubber_band_force =
m_rubber_band_duration =
m_rubber_band_duration =
m_camera_max_accel = m_camera_max_brake =
m_camera_distance = UNDEFINED;
m_gravity_center_shift = Vec3(UNDEFINED);
@@ -150,10 +150,10 @@ void KartProperties::load(const std::string &filename, const std::string &node,
}
m_kart_model.setDefaultPhysicsPosition(m_gravity_center_shift,
m_wheel_radius);
float wheel_base = fabsf( m_kart_model.getWheelPhysicsPosition(0).getY()
-m_kart_model.getWheelPhysicsPosition(2).getY());
m_angle_at_min = asinf(wheel_base/m_min_radius);
m_angle_at_max = asinf(wheel_base/m_max_radius);
m_wheel_base = fabsf( m_kart_model.getWheelPhysicsPosition(0).getY()
-m_kart_model.getWheelPhysicsPosition(2).getY());
m_angle_at_min = asinf(m_wheel_base/m_min_radius);
m_angle_at_max = asinf(m_wheel_base/m_max_radius);
if(m_max_speed_turn == m_min_speed_turn)
m_speed_angle_increase = 0.0;
else
@@ -322,6 +322,7 @@ void KartProperties::checkAllSet(const std::string &filename)
CHECK_NEG(m_friction_slip, "friction-slip" );
CHECK_NEG(m_roll_influence, "roll-influence" );
CHECK_NEG(m_wheel_radius, "wheel-radius" );
// Don't check m_wheel_base here, it is computed later!
CHECK_NEG(m_chassis_linear_damping, "chassis-linear-damping" );
CHECK_NEG(m_chassis_angular_damping, "chassis-angular-damping" );
CHECK_NEG(m_maximum_speed, "maximum-speed" );

View File

@@ -102,6 +102,7 @@ protected:
float m_rubber_band_max_length;/**< Max. length of plunger rubber band.*/
float m_rubber_band_force; /**< Force of an attached rubber band.*/
float m_rubber_band_duration;/**< Duration a rubber band works. */
float m_wheel_base; /**< Wheel base of the kart. */
SFXManager::SFXType m_engine_sfx_type; /**< Engine sound effect. */
@@ -183,6 +184,7 @@ public:
float getFrictionSlip () const {return m_friction_slip; }
float getRollInfluence () const {return m_roll_influence; }
float getWheelRadius () const {return m_wheel_radius; }
float getWheelBase () const {return m_wheel_base; }
float getChassisLinearDamping () const {return m_chassis_linear_damping; }
float getChassisAngularDamping () const {return m_chassis_angular_damping; }
float getMaximumSpeed () const {return m_maximum_speed; }

View File

@@ -1,6 +1,7 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2004-2005 Steve Baker <sjbaker1@airmail.net>
// Copyright (C) 2006-2007 Eduardo Hernandez Munoz
// Copyright (C) 2008 Joerg Henrichs
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@@ -113,20 +114,20 @@ DefaultRobot::~DefaultRobot()
//-----------------------------------------------------------------------------
//TODO: if the AI is crashing constantly, make it move backwards in a straight
//line, then move forward while turning.
void DefaultRobot::update( float delta )
void DefaultRobot::update(float dt)
{
m_track_sector = m_world->m_kart_info[ getWorldKartId() ].m_track_sector;
// The client does not do any AI computations.
if(network_manager->getMode()==NetworkManager::NW_CLIENT)
{
AutoKart::update( delta );
AutoKart::update(dt);
return;
}
if( RaceManager::getWorld()->isStartPhase() )
{
handleRaceStart();
AutoKart::update( delta );
AutoKart::update(dt);
return;
}
@@ -154,15 +155,15 @@ void DefaultRobot::update( float delta )
findCurve();
/*Response handling functions*/
handleAcceleration( delta );
handleSteering();
handleItems( delta, steps );
handleRescue( delta );
handleAcceleration(dt);
handleSteering(dt);
handleItems(dt, steps);
handleRescue(dt);
handleBraking();
handleNitro();
/*And obviously general kart stuff*/
AutoKart::update( delta );
AutoKart::update(dt);
m_collided = false;
} // update
@@ -237,7 +238,7 @@ void DefaultRobot::handleBraking()
} // handleBraking
//-----------------------------------------------------------------------------
void DefaultRobot::handleSteering()
void DefaultRobot::handleSteering(float dt)
{
const unsigned int DRIVELINE_SIZE = (unsigned int)m_track->m_driveline.size();
const size_t NEXT_SECTOR = (unsigned int)m_track_sector + 1 < DRIVELINE_SIZE
@@ -248,11 +249,10 @@ void DefaultRobot::handleSteering()
*finite state machine.
*/
//Reaction to being outside of the road
if( fabsf(m_world->getDistanceToCenterForKart( getWorldKartId() )) + 0.5 >
if( fabsf(m_world->getDistanceToCenterForKart( getWorldKartId() )) + 0.5f >
m_track->getWidth()[m_track_sector] )
{
steer_angle = steerToPoint( m_track->
m_driveline[NEXT_SECTOR] );
steer_angle = steerToPoint( m_track->m_driveline[NEXT_SECTOR], dt );
#ifdef AI_DEBUG
std::cout << "- Outside of road: steer to center point." <<
@@ -305,7 +305,7 @@ void DefaultRobot::handleSteering()
{
sgVec2 straight_point;
findNonCrashingPoint( straight_point );
steer_angle = steerToPoint( straight_point );
steer_angle = steerToPoint(straight_point, dt);
}
break;
@@ -537,7 +537,6 @@ void DefaultRobot::handleNitro()
if( 1.3f*getEnergy() >= finish - m_world->getTime() )
{
m_controls.wheelie = true;
printf("lasp lap --> nitro.\n");
return;
}
}
@@ -596,13 +595,52 @@ float DefaultRobot::steerToAngle (const size_t SECTOR, const float ANGLE)
} // steerToAngle
//-----------------------------------------------------------------------------
float DefaultRobot::steerToPoint( const sgVec2 POINT )
/** Computes the steering angle to reach a certain point. Note that the
* steering angle depends on the velocity of the kart (simple setting the
* steering angle towards the angle the point has is not correct: a slower
* kart will obviously turn less in one time step than a faster kart).
* \param point Point to steer towards.
* \param dt Time step.
*/
float DefaultRobot::steerToPoint(const sgVec2 point, float dt)
{
const float dx = POINT[0] - getXYZ().getX();
const float dy = POINT[1] - getXYZ().getY();
float theta = -atan2(dx, dy);
float steer_angle = theta - getHPR().getHeading();
steer_angle = normalizeAngle(steer_angle);
// No sense steering if we are not driving.
if(getSpeed()==0) return 0.0f;
const float dx = point[0] - getXYZ().getX();
const float dy = point[1] - getXYZ().getY();
/** Angle from the kart position to the point in world coordinates. */
float theta = -atan2(dx, dy);
// Angle is the point is relative to the heading - but take the current
// angular velocity into account, too. The value is multiplied by two
// to avoid 'oversteering' - experimentally found.
float angle_2_point = theta - getHPR().getHeading()
- dt*m_body->getAngularVelocity().getZ()*2.0f;
angle_2_point = normalizeAngle(angle_2_point);
if(fabsf(angle_2_point)<0.1) return 0.0f;
/** To understand this code, consider how a given steering angle determines
* the angle the kart is facing after one timestep:
* sin(steer_angle) = wheel_base / radius; --> compute radius of turn
* circumference = radius * 2 * M_PI; --> circumference of turn circle
* The kart drives dt*V units during a timestep of size dt. So the ratio
* of the driven distance to the circumference is the same as the angle
* the whole circle, or:
* angle / (2*M_PI) = dt*V / circumference
* Reversly, if the angle to drive to is given, the circumference can be
* computed, and from that the turn radius, and then the steer angle.
* (note: the 2*M_PI can be removed from the computations)
*/
float radius = dt*getSpeed()/angle_2_point;
float sin_steer_angle = m_kart_properties->getWheelBase()/radius;
#ifdef DEBUG_OUTPUT
printf("theta %f a2p %f angularv %f radius %f ssa %f\n",
theta, angle_2_point, m_body->getAngularVelocity().getZ(),
radius, sin_steer_angle);
#endif
if(sin_steer_angle <= -1.0f) return -getMaxSteerAngle()*m_skidding_threshold;
if(sin_steer_angle >= 1.0f) return getMaxSteerAngle()*m_skidding_threshold;
float steer_angle = asin(sin_steer_angle);
return steer_angle;
} // steerToPoint
@@ -665,6 +703,7 @@ void DefaultRobot::checkCrashes( const int STEPS, const Vec3& pos )
/*Find if we crash with the drivelines*/
m_track->findRoadSector(step_coord, &m_sector);
#undef SHOW_FUTURE_PATH
#ifdef SHOW_FUTURE_PATH
ssgaSphere *sphere = new ssgaSphere;
@@ -873,7 +912,7 @@ int DefaultRobot::calcSteps()
void DefaultRobot::setSteering( float angle )
{
angle = angle / getMaxSteerAngle();
m_controls.jump = fabsf(angle)>m_skidding_threshold;
m_controls.jump = fabsf(angle)>=m_skidding_threshold;
if (angle > 1.0f) m_controls.lr = 1.0f;
else if(angle < -1.0f) m_controls.lr = -1.0f;

View File

@@ -137,7 +137,7 @@ private:
*/
void handleRaceStart();
void handleAcceleration(const float DELTA);
void handleSteering();
void handleSteering(float dt);
void handleItems(const float DELTA, const int STEPS);
void handleRescue(const float DELTA);
void handleBraking();
@@ -145,7 +145,7 @@ private:
/*Lower level functions not called directly from update()*/
float steerToAngle(const size_t SECTOR, const float ANGLE);
float steerToPoint(const sgVec2 POINT);
float steerToPoint(const sgVec2 point, float dt);
void checkCrashes(const int STEPS, const Vec3& pos);
void findNonCrashingPoint(sgVec2 result);