1) Very first version of improved AI: it does use skidding,
and braking behaviour is improved. 2) The track angle was switched from degrees to rad. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/trunk/supertuxkart@2577 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
parent
e76c1dc87c
commit
66859e11e9
@ -147,9 +147,10 @@ supertuxkart_SOURCES = main.cpp \
|
||||
gui/challenges_menu.cpp gui/challenges_menu.hpp \
|
||||
gui/feature_unlocked.cpp gui/feature_unlocked.hpp \
|
||||
gui/font.hpp gui/font.cpp \
|
||||
physics/physics.cpp physics/physics.hpp \
|
||||
physics/physics.cpp physics/physics.hpp \
|
||||
physics/kart_motion_state.hpp \
|
||||
robots/default_robot.cpp robots/default_robot.hpp \
|
||||
robots/default_robot.cpp robots/default_robot.hpp \
|
||||
robots/track_info.cpp robots/track_info.hpp \
|
||||
modes/follow_the_leader.cpp modes/follow_the_leader.hpp \
|
||||
modes/standard_race.cpp modes/standard_race.hpp \
|
||||
modes/clock.cpp modes/clock.hpp \
|
||||
|
@ -966,6 +966,10 @@
|
||||
RelativePath="../../../src\robots\default_robot.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\robots\track_info.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="challenges"
|
||||
@ -1544,6 +1548,10 @@
|
||||
RelativePath="../../../src\robots\default_robot.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\robots\track_info.hpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="challenges"
|
||||
|
@ -72,7 +72,6 @@ void LinearWorld::init()
|
||||
info.m_time_at_last_lap = 99999.9f;
|
||||
|
||||
m_kart_info.push_back(info);
|
||||
|
||||
}// next kart
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -488,7 +487,7 @@ void LinearWorld::moveKartAfterRescue(Kart* kart, btRigidBody* body)
|
||||
kart->setXYZ( RaceManager::getTrack()->trackToSpatial(info.m_track_sector) );
|
||||
|
||||
btQuaternion heading(btVector3(0.0f, 0.0f, 1.0f),
|
||||
DEGREE_TO_RAD(RaceManager::getTrack()->m_angle[info.m_track_sector]) );
|
||||
RaceManager::getTrack()->m_angle[info.m_track_sector] );
|
||||
kart->setRotation(heading);
|
||||
|
||||
// A certain epsilon is added here to the Z coordinate (0.1), in case
|
||||
@ -498,11 +497,12 @@ void LinearWorld::moveKartAfterRescue(Kart* kart, btRigidBody* body)
|
||||
btTransform pos;
|
||||
pos.setOrigin(kart->getXYZ()+btVector3(0, 0, 0.5f*kart->getKartHeight()+0.1f));
|
||||
pos.setRotation(btQuaternion(btVector3(0.0f, 0.0f, 1.0f),
|
||||
DEGREE_TO_RAD(RaceManager::getTrack()->m_angle[info.m_track_sector])));
|
||||
RaceManager::getTrack()->m_angle[info.m_track_sector]));
|
||||
|
||||
body->setCenterOfMassTransform(pos);
|
||||
|
||||
}
|
||||
} // moveKartAfterRescue
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Find the position (rank) of 'kart' and update it accordingly
|
||||
*/
|
||||
|
@ -109,7 +109,7 @@ void World::init()
|
||||
if(user_config->m_profile)
|
||||
{
|
||||
// In profile mode, load only the old kart
|
||||
newkart = new DefaultRobot(kart_name, position, init_pos);
|
||||
newkart = new DefaultRobot(kart_name, position, init_pos, m_track);
|
||||
// Create a camera for the last kart (since this way more of the
|
||||
// karts can be seen.
|
||||
if(i==race_manager->getNumKarts()-1)
|
||||
@ -523,11 +523,11 @@ Kart* World::loadRobot(const std::string& kart_name, int position,
|
||||
switch(m_random.get(NUM_ROBOTS))
|
||||
{
|
||||
case 0:
|
||||
currentRobot = new DefaultRobot(kart_name, position, init_pos);
|
||||
currentRobot = new DefaultRobot(kart_name, position, init_pos, m_track);
|
||||
break;
|
||||
default:
|
||||
std::cerr << "Warning: Unknown robot, using default." << std::endl;
|
||||
currentRobot = new DefaultRobot(kart_name, position, init_pos);
|
||||
currentRobot = new DefaultRobot(kart_name, position, init_pos, m_track);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -38,36 +38,45 @@
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
#include "constants.hpp"
|
||||
#include "race_manager.hpp"
|
||||
#include "scene.hpp"
|
||||
#include "modes/linear_world.hpp"
|
||||
#include "race_manager.hpp"
|
||||
#include "network/network_manager.hpp"
|
||||
#include "robots/track_info.hpp"
|
||||
|
||||
const TrackInfo *DefaultRobot::m_track_info = NULL;
|
||||
int DefaultRobot::m_num_of_track_info_instances = 0;
|
||||
|
||||
DefaultRobot::DefaultRobot(const std::string& kart_name,
|
||||
int position, const btTransform& init_pos ) :
|
||||
int position, const btTransform& init_pos,
|
||||
const Track *track ) :
|
||||
AutoKart( kart_name, position, init_pos )
|
||||
{
|
||||
if(m_num_of_track_info_instances==0)
|
||||
{
|
||||
m_track_info = new TrackInfo(track);
|
||||
m_num_of_track_info_instances++;
|
||||
}
|
||||
reset();
|
||||
m_kart_length = m_kart_properties->getKartModel()->getLength();
|
||||
|
||||
m_track = RaceManager::getTrack();
|
||||
m_world = dynamic_cast<LinearWorld*>(RaceManager::getWorld());
|
||||
assert(m_world != NULL);
|
||||
|
||||
switch( race_manager->getDifficulty())
|
||||
{
|
||||
case RaceManager::RD_EASY:
|
||||
m_wait_for_players = true;
|
||||
m_wait_for_players = true;
|
||||
m_max_handicap_accel = 0.9f;
|
||||
m_fallback_tactic = FT_AVOID_TRACK_CRASH;
|
||||
m_use_wheelies = false;
|
||||
m_wheelie_check_dist = 0.0f;
|
||||
m_item_tactic = IT_TEN_SECONDS;
|
||||
m_max_start_delay = 0.5f;
|
||||
m_min_steps = 0;
|
||||
m_fallback_tactic = FT_AVOID_TRACK_CRASH;
|
||||
m_item_tactic = IT_TEN_SECONDS;
|
||||
m_max_start_delay = 0.5f;
|
||||
m_min_steps = 0;
|
||||
break;
|
||||
case RaceManager::RD_MEDIUM:
|
||||
m_wait_for_players = true;
|
||||
m_max_handicap_accel = 0.95f;
|
||||
m_fallback_tactic = FT_PARALLEL;
|
||||
m_use_wheelies = true;
|
||||
m_wheelie_check_dist = 0.8f;
|
||||
m_item_tactic = IT_CALCULATE;
|
||||
m_max_start_delay = 0.4f;
|
||||
m_min_steps = 1;
|
||||
@ -76,20 +85,33 @@ DefaultRobot::DefaultRobot(const std::string& kart_name,
|
||||
m_wait_for_players = false;
|
||||
m_max_handicap_accel = 1.0f;
|
||||
m_fallback_tactic = FT_FAREST_POINT;
|
||||
m_use_wheelies = true;
|
||||
m_wheelie_check_dist = 1.0f;
|
||||
m_item_tactic = IT_CALCULATE;
|
||||
m_max_start_delay = 0.1f;
|
||||
m_min_steps = 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} // DefaultRobot
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** The destructor deletes the shared TrackInfo objects if no more DefaultRobot
|
||||
* instances are around.
|
||||
*/
|
||||
DefaultRobot::~DefaultRobot()
|
||||
{
|
||||
m_num_of_track_info_instances--;
|
||||
|
||||
if(m_num_of_track_info_instances==0)
|
||||
{
|
||||
delete m_track_info;
|
||||
}
|
||||
} // ~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 )
|
||||
{
|
||||
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)
|
||||
{
|
||||
@ -99,7 +121,7 @@ void DefaultRobot::update( float delta )
|
||||
|
||||
if( RaceManager::getWorld()->isStartPhase() )
|
||||
{
|
||||
handle_race_start();
|
||||
handleRaceStart();
|
||||
AutoKart::update( delta );
|
||||
return;
|
||||
}
|
||||
@ -121,20 +143,18 @@ void DefaultRobot::update( float delta )
|
||||
}
|
||||
else
|
||||
{
|
||||
steps = calc_steps();
|
||||
steps = calcSteps();
|
||||
}
|
||||
|
||||
check_crashes( steps, getXYZ() );
|
||||
find_curve();
|
||||
checkCrashes( steps, getXYZ() );
|
||||
findCurve();
|
||||
|
||||
/*Response handling functions*/
|
||||
handle_acceleration( delta );
|
||||
handle_steering();
|
||||
handle_items( delta, steps );
|
||||
handle_rescue( delta );
|
||||
handle_wheelie( steps );
|
||||
handle_braking();
|
||||
//TODO:handle jumping
|
||||
handleAcceleration( delta );
|
||||
handleSteering();
|
||||
handleItems( delta, steps );
|
||||
handleRescue( delta );
|
||||
handleBraking();
|
||||
|
||||
/*And obviously general kart stuff*/
|
||||
AutoKart::update( delta );
|
||||
@ -142,16 +162,7 @@ void DefaultRobot::update( float delta )
|
||||
} // update
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void DefaultRobot::handle_wheelie( const int STEPS )
|
||||
{
|
||||
if( m_use_wheelies )
|
||||
{
|
||||
m_controls.wheelie = do_wheelie( STEPS );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void DefaultRobot::handle_braking()
|
||||
void DefaultRobot::handleBraking()
|
||||
{
|
||||
// In follow the leader mode, the kart should brake if they are ahead of
|
||||
// the leader (and not the leader, i.e. don't have initial position 1)
|
||||
@ -162,22 +173,17 @@ void DefaultRobot::handle_braking()
|
||||
m_controls.brake = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME - don't re-create everytime, store at least the lworld
|
||||
LinearWorld* lworld = dynamic_cast<LinearWorld*>(RaceManager::getWorld());
|
||||
assert(lworld != NULL);
|
||||
KartInfo& kart_info = lworld->m_kart_info[ getWorldKartId() ];
|
||||
|
||||
const float MIN_SPEED = RaceManager::getTrack()->getWidth()[kart_info.m_track_sector];
|
||||
|
||||
|
||||
const float MIN_SPEED = m_track->getWidth()[m_track_sector];
|
||||
KartInfo &kart_info = m_world->m_kart_info[ getWorldKartId() ];
|
||||
//We may brake if we are about to get out of the road, but only if the
|
||||
//kart is on top of the road, and if we won't slow down below a certain
|
||||
//limit.
|
||||
if ( m_crashes.m_road && kart_info.m_on_road && getVelocityLC().getY() > MIN_SPEED)
|
||||
{
|
||||
float kart_ang_diff = RaceManager::getTrack()->m_angle[kart_info.m_track_sector] -
|
||||
float kart_ang_diff = m_track->m_angle[m_track_sector] -
|
||||
RAD_TO_DEGREE(getHPR().getHeading());
|
||||
kart_ang_diff = normalize_angle(kart_ang_diff);
|
||||
kart_ang_diff = normalizeAngle(kart_ang_diff);
|
||||
kart_ang_diff = fabsf(kart_ang_diff);
|
||||
|
||||
const float MIN_TRACK_ANGLE = 20.0f;
|
||||
@ -190,7 +196,7 @@ void DefaultRobot::handle_braking()
|
||||
//if the curve angle is bigger than what the kart can steer, brake
|
||||
//even if we are in the inside, because the kart would be 'thrown'
|
||||
//out of the curve.
|
||||
if(!(lworld->getDistanceToCenterForKart(getWorldKartId()) > RaceManager::getTrack()->getWidth()[kart_info.m_track_sector] *
|
||||
if(!(m_world->getDistanceToCenterForKart(getWorldKartId()) > m_track->getWidth()[m_track_sector] *
|
||||
-CURVE_INSIDE_PERC || m_curve_angle > RAD_TO_DEGREE(getMaxSteerAngle())))
|
||||
{
|
||||
m_controls.brake = false;
|
||||
@ -199,7 +205,7 @@ void DefaultRobot::handle_braking()
|
||||
}
|
||||
else if( m_curve_angle < -MIN_TRACK_ANGLE ) //Next curve is right
|
||||
{
|
||||
if(!(lworld->getDistanceToCenterForKart( getWorldKartId() ) < RaceManager::getTrack()->getWidth()[kart_info.m_track_sector] *
|
||||
if(!(m_world->getDistanceToCenterForKart( getWorldKartId() ) < m_track->getWidth()[m_track_sector] *
|
||||
CURVE_INSIDE_PERC || m_curve_angle < -RAD_TO_DEGREE(getMaxSteerAngle())))
|
||||
{
|
||||
m_controls.brake = false;
|
||||
@ -210,10 +216,8 @@ void DefaultRobot::handle_braking()
|
||||
//Brake if the kart's speed is bigger than the speed we need
|
||||
//to go through the curve at the widest angle, or if the kart
|
||||
//is not going straight in relation to the road.
|
||||
float angle_adjust = RaceManager::getTrack()->getAIAngleAdjustment();
|
||||
float speed_adjust = RaceManager::getTrack()->getAICurveSpeedAdjustment();
|
||||
if(getVelocityLC().getY() > speed_adjust*m_curve_target_speed ||
|
||||
kart_ang_diff > angle_adjust*MIN_TRACK_ANGLE )
|
||||
if(getVelocityLC().getY() > m_curve_target_speed ||
|
||||
kart_ang_diff > MIN_TRACK_ANGLE )
|
||||
{
|
||||
#ifdef AI_DEBUG
|
||||
std::cout << "BRAKING" << std::endl;
|
||||
@ -225,29 +229,24 @@ void DefaultRobot::handle_braking()
|
||||
}
|
||||
|
||||
m_controls.brake = false;
|
||||
}
|
||||
} // handleBraking
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void DefaultRobot::handle_steering()
|
||||
void DefaultRobot::handleSteering()
|
||||
{
|
||||
// FIXME - don't re-create everytime, store at least the lworld
|
||||
LinearWorld* lworld = dynamic_cast<LinearWorld*>(RaceManager::getWorld());
|
||||
assert(lworld != NULL);
|
||||
KartInfo& kart_info = lworld->m_kart_info[ getWorldKartId() ];
|
||||
|
||||
const unsigned int DRIVELINE_SIZE = (unsigned int)RaceManager::getTrack()->m_driveline.size();
|
||||
const size_t NEXT_SECTOR = (unsigned int)kart_info.m_track_sector + 1 < DRIVELINE_SIZE ?
|
||||
kart_info.m_track_sector + 1 : 0;
|
||||
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
|
||||
? m_track_sector + 1 : 0;
|
||||
float steer_angle = 0.0f;
|
||||
|
||||
/*The AI responds based on the information we just gathered, using a
|
||||
*finite state machine.
|
||||
*/
|
||||
//Reaction to being outside of the road
|
||||
if( fabsf(lworld->getDistanceToCenterForKart( getWorldKartId() )) + 0.5 >
|
||||
RaceManager::getTrack()->getWidth()[kart_info.m_track_sector] )
|
||||
if( fabsf(m_world->getDistanceToCenterForKart( getWorldKartId() )) + 0.5 >
|
||||
m_track->getWidth()[m_track_sector] )
|
||||
{
|
||||
steer_angle = steer_to_point( RaceManager::getTrack()->
|
||||
steer_angle = steerToPoint( m_track->
|
||||
m_driveline[NEXT_SECTOR] );
|
||||
|
||||
#ifdef AI_DEBUG
|
||||
@ -262,25 +261,25 @@ void DefaultRobot::handle_steering()
|
||||
//-1 = left, 1 = right, 0 = no crash.
|
||||
if( m_start_kart_crash_direction == 1 )
|
||||
{
|
||||
steer_angle = steer_to_angle( NEXT_SECTOR, -90.0f );
|
||||
steer_angle = steerToAngle( NEXT_SECTOR, -M_PI*0.5f );
|
||||
m_start_kart_crash_direction = 0;
|
||||
}
|
||||
else if(m_start_kart_crash_direction == -1)
|
||||
{
|
||||
steer_angle = steer_to_angle( NEXT_SECTOR, 90.0f );
|
||||
steer_angle = steerToAngle( NEXT_SECTOR, M_PI*0.5f);
|
||||
m_start_kart_crash_direction = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(lworld->getDistanceToCenterForKart( getWorldKartId() ) >
|
||||
lworld->getDistanceToCenterForKart( m_crashes.m_kart ))
|
||||
if(m_world->getDistanceToCenterForKart( getWorldKartId() ) >
|
||||
m_world->getDistanceToCenterForKart( m_crashes.m_kart ))
|
||||
{
|
||||
steer_angle = steer_to_angle( NEXT_SECTOR, -90.0f );
|
||||
steer_angle = steerToAngle( NEXT_SECTOR, -M_PI*0.5f );
|
||||
m_start_kart_crash_direction = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
steer_angle = steer_to_angle( NEXT_SECTOR, 90.0f );
|
||||
steer_angle = steerToAngle( NEXT_SECTOR, M_PI*0.5f );
|
||||
m_start_kart_crash_direction = -1;
|
||||
}
|
||||
}
|
||||
@ -299,19 +298,19 @@ void DefaultRobot::handle_steering()
|
||||
case FT_FAREST_POINT:
|
||||
{
|
||||
sgVec2 straight_point;
|
||||
find_non_crashing_point( straight_point );
|
||||
steer_angle = steer_to_point( straight_point );
|
||||
findNonCrashingPoint( straight_point );
|
||||
steer_angle = steerToPoint( straight_point );
|
||||
}
|
||||
break;
|
||||
|
||||
case FT_PARALLEL:
|
||||
steer_angle = steer_to_angle( NEXT_SECTOR, 0.0f );
|
||||
steer_angle = steerToAngle( NEXT_SECTOR, 0.0f );
|
||||
break;
|
||||
|
||||
case FT_AVOID_TRACK_CRASH:
|
||||
if( m_crashes.m_road )
|
||||
{
|
||||
steer_angle = steer_to_angle( kart_info.m_track_sector, 0.0f );
|
||||
steer_angle = steerToAngle( m_track_sector, 0.0f );
|
||||
}
|
||||
else steer_angle = 0.0f;
|
||||
|
||||
@ -324,14 +323,15 @@ void DefaultRobot::handle_steering()
|
||||
|
||||
}
|
||||
// avoid steer vibrations
|
||||
if (fabsf(steer_angle) < 2.0f)
|
||||
if (fabsf(steer_angle) < 2.0f*3.1415/180.0f)
|
||||
steer_angle = 0.f;
|
||||
|
||||
m_controls.lr = angle_to_control( steer_angle );
|
||||
}
|
||||
m_controls.lr = angleToControl( steer_angle );
|
||||
m_controls.jump = fabsf(m_controls.lr)>0.99;
|
||||
} // handleSteering
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void DefaultRobot::handle_items( const float DELTA, const int STEPS )
|
||||
void DefaultRobot::handleItems( const float DELTA, const int STEPS )
|
||||
{
|
||||
m_controls.fire = false;
|
||||
|
||||
@ -339,11 +339,6 @@ void DefaultRobot::handle_items( const float DELTA, const int STEPS )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME - don't re-create everytime, store at least the lworld
|
||||
LinearWorld* lworld = dynamic_cast<LinearWorld*>(RaceManager::getWorld());
|
||||
assert(lworld != NULL);
|
||||
KartInfo& kart_info = lworld->m_kart_info[ getWorldKartId() ];
|
||||
|
||||
m_time_since_last_shot += DELTA;
|
||||
if( m_powerup.getType() != POWERUP_NOTHING )
|
||||
@ -362,8 +357,8 @@ void DefaultRobot::handle_items( const float DELTA, const int STEPS )
|
||||
{
|
||||
case POWERUP_ZIPPER:
|
||||
{
|
||||
const float ANGLE_DIFF = fabsf( normalize_angle(
|
||||
RaceManager::getTrack()->m_angle[kart_info.m_track_sector]-
|
||||
const float ANGLE_DIFF = fabsf( normalizeAngle(
|
||||
m_track->m_angle[m_track_sector]-
|
||||
RAD_TO_DEGREE(getHPR().getHeading()) ) );
|
||||
|
||||
if( m_time_since_last_shot > 10.0f && ANGLE_DIFF <
|
||||
@ -379,8 +374,8 @@ void DefaultRobot::handle_items( const float DELTA, const int STEPS )
|
||||
case POWERUP_CAKE:
|
||||
if( m_time_since_last_shot > 5.0f && m_crashes.m_kart != -1 )
|
||||
{
|
||||
if( (getXYZ()-RaceManager::getKart(m_crashes.m_kart)->getXYZ() ).length_2d() >
|
||||
m_kart_length * 2.5f )
|
||||
if( (getXYZ()-RaceManager::getKart(m_crashes.m_kart)->getXYZ() ).length_2d() >
|
||||
m_kart_length * 2.5f )
|
||||
{
|
||||
m_controls.fire = true;
|
||||
m_time_since_last_shot = 0.0f;
|
||||
@ -405,10 +400,10 @@ void DefaultRobot::handle_items( const float DELTA, const int STEPS )
|
||||
}
|
||||
}
|
||||
return;
|
||||
} // handle_items
|
||||
} // handleItems
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void DefaultRobot::handle_acceleration( const float DELTA )
|
||||
void DefaultRobot::handleAcceleration( const float DELTA )
|
||||
{
|
||||
//Do not accelerate until we have delayed the start enough
|
||||
if( m_time_till_start > 0.0f )
|
||||
@ -443,63 +438,10 @@ void DefaultRobot::handle_acceleration( const float DELTA )
|
||||
}
|
||||
|
||||
m_controls.accel = 1.0f;
|
||||
}
|
||||
} // handleAcceleration
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool DefaultRobot::do_wheelie ( const int STEPS )
|
||||
{
|
||||
if( m_crashes.m_road ) return false;
|
||||
if( m_crashes.m_kart != -1 ) return false;
|
||||
|
||||
// FIXME - don't re-create everytime, store at least the lworld
|
||||
LinearWorld* lworld = dynamic_cast<LinearWorld*>(RaceManager::getWorld());
|
||||
assert(lworld != NULL);
|
||||
KartInfo& kart_info = lworld->m_kart_info[ getWorldKartId() ];
|
||||
|
||||
//We have to be careful with normalizing, because if the source argument
|
||||
//has both the X and Y axis set to 0, it returns nan to the destiny.
|
||||
const Vec3 &VEL = getVelocity();
|
||||
Vec3 vel_normal(VEL.getX(), VEL.getY(), 0.0);
|
||||
float len = vel_normal.length();
|
||||
// Too slow for wheelies, and it avoids normalisation problems.
|
||||
if(len<getMaxSpeed()*getWheelieMaxSpeedRatio()) return false;
|
||||
vel_normal/=len;
|
||||
|
||||
Vec3 step_coord;
|
||||
Vec3 step_track_coord;
|
||||
float distance;
|
||||
|
||||
//FIXME: instead of using 1.5, it should find out how much time it
|
||||
//will pass to stop doing the wheelie completely from the current state.
|
||||
const float CHECK_DIST = 1.5f * m_wheelie_check_dist;
|
||||
|
||||
/* The following method of finding if a position is outside of the track
|
||||
is less accurate than calling findRoadSector(), but a lot faster.
|
||||
*/
|
||||
const int WHEELIE_STEPS = int(( getVelocityLC().getY() * CHECK_DIST )/
|
||||
m_kart_length );
|
||||
|
||||
for( int i = WHEELIE_STEPS; i > STEPS - 1; --i )
|
||||
{
|
||||
step_coord = getXYZ()+vel_normal* m_kart_length * float(i);
|
||||
|
||||
RaceManager::getTrack()->spatialToTrack(step_track_coord, step_coord,
|
||||
m_future_sector );
|
||||
|
||||
distance = step_track_coord[0] > 0.0f ? step_track_coord[0]
|
||||
: -step_track_coord[0];
|
||||
|
||||
if( distance > RaceManager::getTrack()->getWidth()[kart_info.m_track_sector] )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void DefaultRobot::handle_race_start()
|
||||
void DefaultRobot::handleRaceStart()
|
||||
{
|
||||
//FIXME: make karts able to get a penalty for accelerating too soon
|
||||
//like players, should happen to about 20% of the karts in easy,
|
||||
@ -512,10 +454,10 @@ void DefaultRobot::handle_race_start()
|
||||
//smaller depending on the difficulty.
|
||||
m_time_till_start = ( float ) rand() / RAND_MAX * m_max_start_delay;
|
||||
}
|
||||
}
|
||||
} // handleRaceStart
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void DefaultRobot::handle_rescue(const float DELTA)
|
||||
void DefaultRobot::handleRescue(const float DELTA)
|
||||
{
|
||||
//TODO: check if we collided against a dynamic object (ej.:kart) or
|
||||
//against the track's static object.
|
||||
@ -546,48 +488,35 @@ void DefaultRobot::handle_rescue(const float DELTA)
|
||||
{
|
||||
m_time_since_stuck = 0.0f;
|
||||
}
|
||||
}
|
||||
} // handleRescue
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
float DefaultRobot::steer_to_angle (const size_t SECTOR, const float ANGLE)
|
||||
float DefaultRobot::steerToAngle (const size_t SECTOR, const float ANGLE)
|
||||
{
|
||||
float angle = RaceManager::getTrack()->m_angle[SECTOR];
|
||||
float angle = m_track->m_angle[SECTOR];
|
||||
|
||||
//Desired angle minus current angle equals how many angles to turn
|
||||
float steer_angle = angle - RAD_TO_DEGREE(getHPR().getHeading());
|
||||
float steer_angle = angle - getHPR().getHeading();
|
||||
|
||||
steer_angle += ANGLE;
|
||||
steer_angle = normalize_angle( steer_angle );
|
||||
|
||||
steer_angle = normalizeAngle( steer_angle );
|
||||
|
||||
return steer_angle;
|
||||
}
|
||||
} // steerToAngle
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
float DefaultRobot::steer_to_point( const sgVec2 POINT )
|
||||
float DefaultRobot::steerToPoint( const sgVec2 POINT )
|
||||
{
|
||||
const SGfloat ADJACENT_LINE = POINT[0] - getXYZ().getX();
|
||||
const SGfloat OPPOSITE_LINE = POINT[1] - getXYZ().getY();
|
||||
SGfloat theta;
|
||||
|
||||
//Protection from division by zero
|
||||
if( ADJACENT_LINE > 0.0000001 || ADJACENT_LINE < -0.0000001 )
|
||||
{
|
||||
theta = sgATan( OPPOSITE_LINE / ADJACENT_LINE );
|
||||
}
|
||||
else theta = 0;
|
||||
|
||||
//The real value depends on the side of the track that the kart is
|
||||
theta += ADJACENT_LINE < 0.0f ? 90.0f : -90.0f;
|
||||
|
||||
float steer_angle = theta - RAD_TO_DEGREE(getHPR().getHeading());
|
||||
steer_angle = normalize_angle( steer_angle );
|
||||
|
||||
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);
|
||||
return steer_angle;
|
||||
}
|
||||
} // steerToPoint
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void DefaultRobot::check_crashes( const int STEPS, const Vec3& pos )
|
||||
void DefaultRobot::checkCrashes( const int STEPS, const Vec3& pos )
|
||||
{
|
||||
//Right now there are 2 kind of 'crashes': with other karts and another
|
||||
//with the track. The sight line is used to find if the karts crash with
|
||||
@ -596,11 +525,11 @@ void DefaultRobot::check_crashes( const int STEPS, const Vec3& pos )
|
||||
//tell when a kart is going to get out of the track so it steers.
|
||||
|
||||
Vec3 vel_normal;
|
||||
//in this func we use it as a 2d-vector, but later on it is passed
|
||||
//to RaceManager::getTrack()->findRoadSector, there it is used as a 3d-vector
|
||||
//to find distance to plane, so z must be initialized to zero
|
||||
//in this func we use it as a 2d-vector, but later on it is passed
|
||||
//to m_track->findRoadSector, there it is used as a 3d-vector
|
||||
//to find distance to plane, so z must be initialized to zero
|
||||
Vec3 step_coord;
|
||||
SGfloat kart_distance;
|
||||
float kart_distance;
|
||||
|
||||
step_coord.setZ(0.0);
|
||||
|
||||
@ -623,7 +552,7 @@ void DefaultRobot::check_crashes( const int STEPS, const Vec3& pos )
|
||||
|
||||
for(int i = 1; STEPS > i; ++i)
|
||||
{
|
||||
step_coord = pos + vel_normal* m_kart_length * float(i);
|
||||
step_coord = pos + vel_normal* m_kart_length * float(i);
|
||||
|
||||
/* Find if we crash with any kart, as long as we haven't found one
|
||||
* yet
|
||||
@ -635,7 +564,7 @@ void DefaultRobot::check_crashes( const int STEPS, const Vec3& pos )
|
||||
const Kart* kart = RaceManager::getKart(j);
|
||||
if(kart==this||kart->isEliminated()) continue; // ignore eliminated karts
|
||||
|
||||
kart_distance = (step_coord - RaceManager::getKart(j)->getXYZ()).length_2d();
|
||||
kart_distance = (step_coord - RaceManager::getKart(j)->getXYZ()).length_2d();
|
||||
|
||||
if( kart_distance < m_kart_length + 0.125f * i )
|
||||
if( getVelocityLC().getY() > RaceManager::getKart(j)->
|
||||
@ -644,7 +573,7 @@ void DefaultRobot::check_crashes( const int STEPS, const Vec3& pos )
|
||||
}
|
||||
|
||||
/*Find if we crash with the drivelines*/
|
||||
RaceManager::getTrack()->findRoadSector(step_coord, &m_sector);
|
||||
m_track->findRoadSector(step_coord, &m_sector);
|
||||
|
||||
#ifdef SHOW_FUTURE_PATH
|
||||
|
||||
@ -681,12 +610,12 @@ void DefaultRobot::check_crashes( const int STEPS, const Vec3& pos )
|
||||
scene->add( sphere );
|
||||
#endif
|
||||
|
||||
m_future_location[0] = step_coord[0]; m_future_location[1] =
|
||||
step_coord[1];
|
||||
m_future_location[0] = step_coord[0];
|
||||
m_future_location[1] = step_coord[1];
|
||||
|
||||
if( m_sector == Track::UNKNOWN_SECTOR )
|
||||
{
|
||||
m_future_sector = RaceManager::getTrack()->findOutOfRoadSector( step_coord,
|
||||
m_future_sector = m_track->findOutOfRoadSector( step_coord,
|
||||
Track::RS_DONT_KNOW, m_future_sector );
|
||||
m_crashes.m_road = true;
|
||||
break;
|
||||
@ -698,7 +627,7 @@ void DefaultRobot::check_crashes( const int STEPS, const Vec3& pos )
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
} // checkCrashes
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Find the sector that at the longest distance from the kart, that can be
|
||||
@ -706,22 +635,17 @@ void DefaultRobot::check_crashes( const int STEPS, const Vec3& pos )
|
||||
* the two edges of the track is closest to the next curve after wards,
|
||||
* and return the position of that edge.
|
||||
*/
|
||||
void DefaultRobot::find_non_crashing_point( sgVec2 result )
|
||||
void DefaultRobot::findNonCrashingPoint( sgVec2 result )
|
||||
{
|
||||
const unsigned int DRIVELINE_SIZE = (unsigned int)RaceManager::getTrack()->m_driveline.size();
|
||||
|
||||
// FIXME - don't re-create everytime, store at least the lworld
|
||||
LinearWorld* lworld = dynamic_cast<LinearWorld*>(RaceManager::getWorld());
|
||||
assert(lworld != NULL);
|
||||
KartInfo& kart_info = lworld->m_kart_info[ getWorldKartId() ];
|
||||
const unsigned int DRIVELINE_SIZE = (unsigned int)m_track->m_driveline.size();
|
||||
|
||||
unsigned int sector = (unsigned int)kart_info.m_track_sector + 1 < DRIVELINE_SIZE ?
|
||||
kart_info.m_track_sector + 1 : 0;
|
||||
unsigned int sector = (unsigned int)m_track_sector + 1 < DRIVELINE_SIZE
|
||||
? m_track_sector + 1 : 0;
|
||||
int target_sector;
|
||||
|
||||
Vec3 direction;
|
||||
Vec3 step_track_coord;
|
||||
SGfloat distance;
|
||||
float distance;
|
||||
int steps;
|
||||
|
||||
//We exit from the function when we have found a solution
|
||||
@ -732,7 +656,7 @@ void DefaultRobot::find_non_crashing_point( sgVec2 result )
|
||||
target_sector = sector + 1 < DRIVELINE_SIZE ? sector + 1 : 0;
|
||||
|
||||
//direction is a vector from our kart to the sectors we are testing
|
||||
direction = RaceManager::getTrack()->m_driveline[target_sector] - getXYZ();
|
||||
direction = m_track->m_driveline[target_sector] - getXYZ();
|
||||
|
||||
float len=direction.length_2d();
|
||||
steps = int( len / m_kart_length );
|
||||
@ -749,16 +673,16 @@ void DefaultRobot::find_non_crashing_point( sgVec2 result )
|
||||
{
|
||||
step_coord = getXYZ()+direction*m_kart_length * float(i);
|
||||
|
||||
RaceManager::getTrack()->spatialToTrack( step_track_coord, step_coord,
|
||||
m_track->spatialToTrack( step_track_coord, step_coord,
|
||||
sector );
|
||||
|
||||
distance = step_track_coord[0] > 0.0f ? step_track_coord[0]
|
||||
: -step_track_coord[0];
|
||||
|
||||
//If we are outside, the previous sector is what we are looking for
|
||||
if ( distance + m_kart_length * 0.5f > RaceManager::getTrack()->getWidth()[sector] )
|
||||
if ( distance + m_kart_length * 0.5f > m_track->getWidth()[sector] )
|
||||
{
|
||||
sgCopyVec2( result, RaceManager::getTrack()->m_driveline[sector] );
|
||||
sgCopyVec2( result, m_track->m_driveline[sector] );
|
||||
|
||||
#ifdef SHOW_NON_CRASHING_POINT
|
||||
ssgaSphere *sphere = new ssgaSphere;
|
||||
@ -789,7 +713,7 @@ void DefaultRobot::find_non_crashing_point( sgVec2 result )
|
||||
}
|
||||
sector = target_sector;
|
||||
}
|
||||
}
|
||||
} // findNonCrashingPoint
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void DefaultRobot::reset()
|
||||
@ -817,13 +741,13 @@ void DefaultRobot::reset()
|
||||
} // reset
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
inline float DefaultRobot::normalize_angle( float angle )
|
||||
inline float DefaultRobot::normalizeAngle(float angle)
|
||||
{
|
||||
while( angle > 360.0 ) angle -= 360;
|
||||
while( angle < -360.0 ) angle += 360;
|
||||
while( angle > 2*M_PI ) angle -= 2*M_PI;
|
||||
while( angle < -2*M_PI ) angle += 2*M_PI;
|
||||
|
||||
if( angle > 180.0 ) angle -= 360.0;
|
||||
else if( angle < -180.0 ) angle += 360.0;
|
||||
if( angle > M_PI ) angle -= 2*M_PI;
|
||||
else if( angle < -M_PI ) angle += 2*M_PI;
|
||||
|
||||
return angle;
|
||||
}
|
||||
@ -833,7 +757,7 @@ inline float DefaultRobot::normalize_angle( float angle )
|
||||
* and gets the number of steps to use for the sight line of the kart.
|
||||
* The calling sequence guarantees that m_future_sector is not UNKNOWN.
|
||||
*/
|
||||
int DefaultRobot::calc_steps()
|
||||
int DefaultRobot::calcSteps()
|
||||
{
|
||||
int steps = int( getVelocityLC().getY() / m_kart_length );
|
||||
if( steps < m_min_steps ) steps = m_min_steps;
|
||||
@ -843,20 +767,20 @@ int DefaultRobot::calc_steps()
|
||||
if( fabsf(m_controls.lr) > 0.95 )
|
||||
{
|
||||
const int WIDTH_STEPS =
|
||||
(int)( RaceManager::getTrack()->getWidth()[m_future_sector]
|
||||
(int)( m_track->getWidth()[m_future_sector]
|
||||
/( m_kart_length * 2.0 ) );
|
||||
|
||||
steps += WIDTH_STEPS;
|
||||
}
|
||||
|
||||
return steps;
|
||||
}
|
||||
} // calcSteps
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Translates coordinates from an angle(in degrees) to values within the range
|
||||
* of -1.0 to 1.0 to use the same format as the KartControl::lr variable.
|
||||
*/
|
||||
float DefaultRobot::angle_to_control( float angle ) const
|
||||
float DefaultRobot::angleToControl( float angle ) const
|
||||
{
|
||||
angle = angle / getMaxSteerAngle();
|
||||
|
||||
@ -864,7 +788,7 @@ float DefaultRobot::angle_to_control( float angle ) const
|
||||
else if(angle < -1.0f) return -1.0f;
|
||||
|
||||
return angle;
|
||||
}
|
||||
} // angleToControl
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Finds the approximate radius of a track's curve. It needs two arguments,
|
||||
@ -875,7 +799,7 @@ float DefaultRobot::angle_to_control( float angle ) const
|
||||
* the two arguments to use the drivelines as the first and last point; the
|
||||
* middle sector is averaged.
|
||||
*/
|
||||
float DefaultRobot::get_approx_radius(const int START, const int END) const
|
||||
float DefaultRobot::getApproxRadius(const int START, const int END) const
|
||||
{
|
||||
const int MIDDLE = (START + END) / 2;
|
||||
|
||||
@ -893,36 +817,36 @@ float DefaultRobot::get_approx_radius(const int START, const int END) const
|
||||
|
||||
if(m_inner_curve == -1)
|
||||
{
|
||||
X1 = RaceManager::getTrack()->m_left_driveline[START][0];
|
||||
Y1 = RaceManager::getTrack()->m_left_driveline[START][1];
|
||||
X1 = m_track->m_left_driveline[START][0];
|
||||
Y1 = m_track->m_left_driveline[START][1];
|
||||
|
||||
X2 = RaceManager::getTrack()->m_left_driveline[MIDDLE][0];
|
||||
Y2 = RaceManager::getTrack()->m_left_driveline[MIDDLE][1];
|
||||
X2 = m_track->m_left_driveline[MIDDLE][0];
|
||||
Y2 = m_track->m_left_driveline[MIDDLE][1];
|
||||
|
||||
X3 = RaceManager::getTrack()->m_left_driveline[END][0];
|
||||
Y3 = RaceManager::getTrack()->m_left_driveline[END][1];
|
||||
X3 = m_track->m_left_driveline[END][0];
|
||||
Y3 = m_track->m_left_driveline[END][1];
|
||||
}
|
||||
else if (m_inner_curve == 0)
|
||||
{
|
||||
X1 = RaceManager::getTrack()->m_driveline[START][0];
|
||||
Y1 = RaceManager::getTrack()->m_driveline[START][1];
|
||||
X1 = m_track->m_driveline[START][0];
|
||||
Y1 = m_track->m_driveline[START][1];
|
||||
|
||||
X2 = RaceManager::getTrack()->m_driveline[MIDDLE][0];
|
||||
Y2 = RaceManager::getTrack()->m_driveline[MIDDLE][1];
|
||||
X2 = m_track->m_driveline[MIDDLE][0];
|
||||
Y2 = m_track->m_driveline[MIDDLE][1];
|
||||
|
||||
X3 = RaceManager::getTrack()->m_driveline[END][0];
|
||||
Y3 = RaceManager::getTrack()->m_driveline[END][1];
|
||||
X3 = m_track->m_driveline[END][0];
|
||||
Y3 = m_track->m_driveline[END][1];
|
||||
}
|
||||
else if (m_inner_curve == 1)
|
||||
{
|
||||
X1 = RaceManager::getTrack()->m_right_driveline[START][0];
|
||||
Y1 = RaceManager::getTrack()->m_right_driveline[START][1];
|
||||
X1 = m_track->m_right_driveline[START][0];
|
||||
Y1 = m_track->m_right_driveline[START][1];
|
||||
|
||||
X2 = RaceManager::getTrack()->m_right_driveline[MIDDLE][0];
|
||||
Y2 = RaceManager::getTrack()->m_right_driveline[MIDDLE][1];
|
||||
X2 = m_track->m_right_driveline[MIDDLE][0];
|
||||
Y2 = m_track->m_right_driveline[MIDDLE][1];
|
||||
|
||||
X3 = RaceManager::getTrack()->m_right_driveline[END][0];
|
||||
Y3 = RaceManager::getTrack()->m_right_driveline[END][1];
|
||||
X3 = m_track->m_right_driveline[END][0];
|
||||
Y3 = m_track->m_right_driveline[END][1];
|
||||
}
|
||||
|
||||
const float A = X2 - X1;
|
||||
@ -941,38 +865,31 @@ float DefaultRobot::get_approx_radius(const int START, const int END) const
|
||||
const float radius = sqrt( ( X1 - pX) * ( X1 - pX) + (Y1 - pY) * (Y1 - pY) );
|
||||
|
||||
return radius;
|
||||
}
|
||||
} // getApproxRadius
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/**Find_curve() gathers info about the closest sectors ahead: the curve
|
||||
/**FindCurve() gathers info about the closest sectors ahead: the curve
|
||||
* angle, the direction of the next turn, and the optimal speed at which the
|
||||
* curve can be travelled at it's widest angle.
|
||||
*
|
||||
* The number of sectors that form the curve is dependant on the kart's speed.
|
||||
*/
|
||||
void DefaultRobot::find_curve()
|
||||
void DefaultRobot::findCurve()
|
||||
{
|
||||
// FIXME - don't re-create everytime, store at least the lworld
|
||||
LinearWorld* lworld = dynamic_cast<LinearWorld*>(RaceManager::getWorld());
|
||||
assert(lworld != NULL);
|
||||
KartInfo& kart_info = lworld->m_kart_info[ getWorldKartId() ];
|
||||
|
||||
const int DRIVELINE_SIZE = (unsigned int)RaceManager::getTrack()->m_driveline.size();
|
||||
const int DRIVELINE_SIZE = (unsigned int)m_track->m_driveline.size();
|
||||
float total_dist = 0.0f;
|
||||
int next_hint = kart_info.m_track_sector;
|
||||
int next_hint = m_track_sector;
|
||||
int i;
|
||||
|
||||
for(i = kart_info.m_track_sector; total_dist < getVelocityLC().getY(); i = next_hint)
|
||||
for(i = m_track_sector; total_dist < getVelocityLC().getY(); i = next_hint)
|
||||
{
|
||||
next_hint = i + 1 < DRIVELINE_SIZE ? i + 1 : 0;
|
||||
total_dist += sgDistanceVec2(RaceManager::getTrack()->m_driveline[i], RaceManager::getTrack()->m_driveline[next_hint]);
|
||||
total_dist += sgDistanceVec2(m_track->m_driveline[i], m_track->m_driveline[next_hint]);
|
||||
}
|
||||
|
||||
|
||||
m_curve_angle = normalize_angle(RaceManager::getTrack()->m_angle[i] - RaceManager::getTrack()->m_angle[kart_info.m_track_sector]);
|
||||
m_curve_angle = normalizeAngle(m_track->m_angle[i] - m_track->m_angle[m_track_sector]);
|
||||
m_inner_curve = m_curve_angle > 0.0 ? -1 : 1;
|
||||
// FIXME: 0.9 is the tire grip - but this was never used. For now this
|
||||
// 0.9 is left in place to reproduce the same results and AI behaviour,
|
||||
// but this function should be updated to bullet physics
|
||||
m_curve_target_speed = sgSqrt(get_approx_radius(kart_info.m_track_sector, i) * RaceManager::getTrack()->getGravity() * 0.9f);
|
||||
}
|
||||
|
||||
m_curve_target_speed = getMaxSpeed();
|
||||
} // findCurve
|
||||
|
@ -21,6 +21,10 @@
|
||||
|
||||
#include "karts/auto_kart.hpp"
|
||||
|
||||
class Track;
|
||||
class LinearWorld;
|
||||
class TrackInfo;
|
||||
|
||||
class DefaultRobot : public AutoKart
|
||||
{
|
||||
private:
|
||||
@ -94,6 +98,15 @@ private:
|
||||
float m_curve_target_speed;
|
||||
float m_curve_angle;
|
||||
|
||||
/** Keep a pointer to the track to reduce calls */
|
||||
Track *m_track;
|
||||
|
||||
/** Keep a pointer to world. */
|
||||
LinearWorld *m_world;
|
||||
/** Cache kart_info.m_track_sector. */
|
||||
int m_track_sector;
|
||||
|
||||
|
||||
float m_time_since_stuck;
|
||||
|
||||
int m_start_kart_crash_direction; //-1 = left, 1 = right, 0 = no crash.
|
||||
@ -101,42 +114,48 @@ private:
|
||||
/** Length of the kart, storing it here saves many function calls. */
|
||||
float m_kart_length;
|
||||
|
||||
/** All AIs share the track info object, so that its information needs
|
||||
* only to be computed once. */
|
||||
static const TrackInfo *m_track_info;
|
||||
/** This counts how many AIs have a pointer to the TrackInfo object. If
|
||||
* this number reaches zero, the shared TrackInfo object is
|
||||
* deallocated. */
|
||||
static int m_num_of_track_info_instances;
|
||||
|
||||
int m_sector;
|
||||
|
||||
/*Functions called directly from update(). They all represent an action
|
||||
*that can be done, and end up setting their respective m_controls
|
||||
*variable, except handle_race_start() that isn't associated with any
|
||||
*specific action (more like, associated with inaction).
|
||||
*/
|
||||
void handle_race_start();
|
||||
void handle_acceleration(const float DELTA);
|
||||
void handle_steering();
|
||||
void handle_items(const float DELTA, const int STEPS);
|
||||
void handle_rescue(const float DELTA);
|
||||
void handle_braking();
|
||||
void handle_wheelie(const int STEPS);
|
||||
void handleRaceStart();
|
||||
void handleAcceleration(const float DELTA);
|
||||
void handleSteering();
|
||||
void handleItems(const float DELTA, const int STEPS);
|
||||
void handleRescue(const float DELTA);
|
||||
void handleBraking();
|
||||
|
||||
/*Lower level functions not called directly from update()*/
|
||||
float steer_to_angle(const size_t SECTOR, const float ANGLE);
|
||||
float steer_to_point(const sgVec2 POINT);
|
||||
float steerToAngle(const size_t SECTOR, const float ANGLE);
|
||||
float steerToPoint(const sgVec2 POINT);
|
||||
|
||||
bool do_wheelie(const int STEPS);
|
||||
void check_crashes(const int STEPS, const Vec3& pos);
|
||||
void find_non_crashing_point(sgVec2 result);
|
||||
void checkCrashes(const int STEPS, const Vec3& pos);
|
||||
void findNonCrashingPoint(sgVec2 result);
|
||||
|
||||
float normalize_angle (float angle);
|
||||
int calc_steps();
|
||||
|
||||
float angle_to_control(float angle) const;
|
||||
float get_approx_radius(const int START, const int END) const;
|
||||
void find_curve();
|
||||
int m_sector;
|
||||
float normalizeAngle(float angle);
|
||||
int calcSteps();
|
||||
float angleToControl(float angle) const;
|
||||
float getApproxRadius(const int START, const int END) const;
|
||||
void findCurve();
|
||||
|
||||
public:
|
||||
DefaultRobot(const std::string& kart_name, int position,
|
||||
const btTransform& init_pos);
|
||||
|
||||
void update (float delta) ;
|
||||
void reset ();
|
||||
virtual void crashed(Kart *k) {if(k) m_collided = true;};
|
||||
DefaultRobot(const std::string& kart_name, int position,
|
||||
const btTransform& init_pos, const Track *track);
|
||||
~DefaultRobot();
|
||||
void update (float delta) ;
|
||||
void reset ();
|
||||
virtual void crashed (Kart *k) {if(k) m_collided = true;};
|
||||
};
|
||||
|
||||
#endif
|
||||
|
72
src/robots/track_info.cpp
Executable file
72
src/robots/track_info.cpp
Executable file
@ -0,0 +1,72 @@
|
||||
// $Id: track_info.cpp 2547 2008-12-02 13:01:39Z hikerstk $
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// 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
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "constants.hpp"
|
||||
#include "track.hpp"
|
||||
#include "robots/track_info.hpp"
|
||||
|
||||
TrackInfo::TrackInfo(const Track *track)
|
||||
{
|
||||
m_track = track;
|
||||
setupSteerInfo();
|
||||
} // TrackInfo
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Creates the steer-info array.
|
||||
*/
|
||||
void TrackInfo::setupSteerInfo()
|
||||
{
|
||||
// First find the beginning of a new section, i.e. a place where the track
|
||||
// direction changes from either straight to curve or the other way round.
|
||||
int i = 0;
|
||||
int num_drivelines = m_track->m_driveline.size();
|
||||
float current_angle = m_track->m_angle[i];
|
||||
while(i<num_drivelines)
|
||||
{
|
||||
DirectionType dir = computeDirection(i);
|
||||
i++;
|
||||
}
|
||||
} // setupSteerInfo
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
TrackInfo::DirectionType TrackInfo::computeDirection(int i)
|
||||
{
|
||||
int i_prev = i-1;
|
||||
if(i_prev<0) i_prev = m_track->m_angle.size()-1;
|
||||
float prev_angle = m_track->m_angle[i_prev];
|
||||
float angle = m_track->m_angle[i];
|
||||
|
||||
float diff = prev_angle - angle;
|
||||
while( diff> 2*M_PI ) diff -= 2*M_PI;
|
||||
while( diff < -2*M_PI ) diff += 2*M_PI;
|
||||
|
||||
if( diff > M_PI ) diff -= 2*M_PI;
|
||||
else if( diff < -M_PI ) diff+= 2*M_PI;
|
||||
|
||||
|
||||
const float curve_degree = 15*M_PI/180.0f;
|
||||
DirectionType t = DIR_STRAIGHT;
|
||||
if (diff <-curve_degree)
|
||||
t = DIR_LEFT;
|
||||
else if (diff > curve_degree)
|
||||
t = DIR_RIGHT;
|
||||
return t;
|
||||
} // computeDirection
|
||||
|
||||
// ----------------------------------------------------------------------------
|
61
src/robots/track_info.hpp
Executable file
61
src/robots/track_info.hpp
Executable file
@ -0,0 +1,61 @@
|
||||
// $Id: track_info.hpp 2547 2008-12-02 13:01:39Z hikerstk $
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// 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
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef HEADER_TRACK_INFO_HPP
|
||||
#define HEADER_TRACK_INFO_HPP
|
||||
|
||||
#include <vector>
|
||||
|
||||
class Track;
|
||||
|
||||
/** This class is used to pre-compute some track information used by the AI,
|
||||
* e.g. length of straight sections, turn radius etc.
|
||||
* Each AI share this information, so it's only done once per track.
|
||||
*/
|
||||
class TrackInfo
|
||||
{
|
||||
/** The direction of the drivelines: straight ahead, or a turn. */
|
||||
enum DirectionType {DIR_STRAIGHT, DIR_LEFT, DIR_RIGHT};
|
||||
|
||||
/** This class stores information for a set of consecutive driveline
|
||||
* points. E.g points that form a straight line, or a left/right turn.
|
||||
*/
|
||||
class SteerInfo
|
||||
{
|
||||
public:
|
||||
DirectionType m_type;
|
||||
}; // SteerInfo
|
||||
|
||||
/** The list of all steer info objects. */
|
||||
std::vector<SteerInfo> m_steer_info;
|
||||
/** The mapping of driveline points to steer infos. Several driveline
|
||||
* points will have the same steer info object. */
|
||||
std::vector<int> m_driveline_2_steer_info;
|
||||
|
||||
/** Pointer to the track. */
|
||||
const Track *m_track;
|
||||
|
||||
void setupSteerInfo();
|
||||
|
||||
DirectionType computeDirection(int i);
|
||||
public:
|
||||
TrackInfo(const Track *track);
|
||||
}; // TrackInfo
|
||||
|
||||
#endif
|
@ -809,8 +809,6 @@ void Track::loadTrack(std::string filename_)
|
||||
m_fog_start = 0.0f;
|
||||
m_fog_end = 1000.0f;
|
||||
m_gravity = 9.80665f;
|
||||
m_AI_angle_adjustment = 1.0f;
|
||||
m_AI_curve_speed_adjustment = 1.0f;
|
||||
|
||||
sgSetVec3 ( m_sun_position, 0.4f, 0.4f, 0.4f );
|
||||
sgSetVec4 ( m_sky_color, 0.3f, 0.7f, 0.9f, 1.0f );
|
||||
@ -858,8 +856,6 @@ void Track::loadTrack(std::string filename_)
|
||||
LISP->get ("sun-diffuse", m_diffuse_col);
|
||||
LISP->get ("gravity", m_gravity);
|
||||
LISP->get ("arena", m_is_arena);
|
||||
LISP->get ("AI-angle-adjust", m_AI_angle_adjustment);
|
||||
LISP->get ("AI-curve-speed-adjust", m_AI_curve_speed_adjustment);
|
||||
LISP->getVector("groups", m_groups);
|
||||
if(m_groups.size()==0)
|
||||
m_groups.push_back("standard");
|
||||
@ -935,19 +931,13 @@ Track::loadDriveline()
|
||||
m_path_width.push_back(width);
|
||||
}
|
||||
|
||||
size_t next;
|
||||
float adjacent_line, opposite_line;
|
||||
SGfloat theta;
|
||||
|
||||
for(unsigned int i = 0; i < DRIVELINE_SIZE; ++i)
|
||||
{
|
||||
next = i + 1 >= DRIVELINE_SIZE ? 0 : i + 1;
|
||||
adjacent_line = m_driveline[next].getX() - m_driveline[i].getX();
|
||||
opposite_line = m_driveline[next].getY() - m_driveline[i].getY();
|
||||
|
||||
theta = sgATan(opposite_line/adjacent_line);
|
||||
theta += adjacent_line < 0.0f ? 90.0f : -90.0f;
|
||||
unsigned int next = i + 1 >= DRIVELINE_SIZE ? 0 : i + 1;
|
||||
float dx = m_driveline[next].getX() - m_driveline[i].getX();
|
||||
float dy = m_driveline[next].getY() - m_driveline[i].getY();
|
||||
|
||||
float theta = -atan2(dx, dy);
|
||||
m_angle.push_back(theta);
|
||||
}
|
||||
|
||||
|
@ -54,11 +54,6 @@ private:
|
||||
ssgBranch* m_model;
|
||||
TriangleMesh* m_track_mesh;
|
||||
TriangleMesh* m_non_collision_mesh;
|
||||
// The next two variables are for AI improvements: the AI sometimes does
|
||||
// not estimate curve speed and/or angle correctly, resulting in too much
|
||||
// braking. These factors are used to adjust this.
|
||||
float m_AI_angle_adjustment;
|
||||
float m_AI_curve_speed_adjustment;
|
||||
bool m_has_final_camera;
|
||||
Vec3 m_camera_final_position;
|
||||
Vec3 m_camera_final_hpr;
|
||||
@ -170,8 +165,6 @@ public:
|
||||
const float& getFogDensity () const {return m_fog_density; }
|
||||
const float& getFogStart () const {return m_fog_start; }
|
||||
const float& getFogEnd () const {return m_fog_end; }
|
||||
const float& getAIAngleAdjustment () const {return m_AI_angle_adjustment;}
|
||||
const float& getAICurveSpeedAdjustment() const {return m_AI_curve_speed_adjustment;}
|
||||
const sgVec4& getSkyColor () const {return m_sky_color; }
|
||||
const std::string& getDescription () const {return m_description; }
|
||||
const std::string& getDesigner () const {return m_designer; }
|
||||
|
Loading…
Reference in New Issue
Block a user