1) Follow the leader mode now removes the first kart if

the leader is not the first.
2) AI karts brake if they are ahead of the leader
3) The leader has now the text 'leader' displayed next
   to the item.
4) The ranks in the leader results table are now correct
   (starting with 1 instead of 2)
5) Fixed two potential bugs, which might result in
   triggering an assert.
6) Replaced assert (in case that it should get triggered
   again) with useful messages to stderr.


git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/trunk/supertuxkart@1688 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk 2008-04-17 00:20:06 +00:00
parent 3612996109
commit a53ca214c5
6 changed files with 62 additions and 29 deletions

View File

@ -121,7 +121,7 @@ LeaderResult::LeaderResult()
char sTime[20]; char sTime[20];
TimeToString(race_time[i], sTime); TimeToString(race_time[i], sTime);
sprintf((char*)(m_score + MAX_STR_LEN * i), "%d. %s %d %s", sprintf((char*)(m_score + MAX_STR_LEN * i), "%d. %s %d %s",
i + 1, race_manager->getKartName(position[i]).c_str(), scores[i], sTime ); i , race_manager->getKartName(position[i]).c_str(), scores[i], sTime );
widget_manager->addWgt(WTOK_FIRSTKART + i, 40, 5); widget_manager->addWgt(WTOK_FIRSTKART + i, 40, 5);
widget_manager->showWgtRect(WTOK_FIRSTKART + i); widget_manager->showWgtRect(WTOK_FIRSTKART + i);

View File

@ -381,8 +381,8 @@ void RaceGUI::drawPlayerIcons ()
glDisable(GL_CULL_FACE); glDisable(GL_CULL_FACE);
if(laps_of_leader>0 && // Display position during first lap if(laps_of_leader>0 && // Display position during first lap
(world->getTime() - kart->getTimeAtLap()<5.0f || (world->getTime() - kart->getTimeAtLap()<5.0f || lap!=laps_of_leader) &&
lap!=laps_of_leader)) race_manager->raceHasLaps())
{ // Display for 5 seconds { // Display for 5 seconds
char str[256]; char str[256];
if(position==1) if(position==1)
@ -398,9 +398,13 @@ void RaceGUI::drawPlayerIcons ()
str[0]='+'; str[1]=0; str[0]='+'; str[1]=0;
TimeToString(timeBehind, str+1); TimeToString(timeBehind, str+1);
} }
if(race_manager->raceHasLaps()) font_race->PrintShadow(str, 30, ICON_PLAYER_WIDHT+x, y+5,
font_race->PrintShadow(str, 30, ICON_PLAYER_WIDHT+x, y+5, red, green, blue);
red, green, blue); }
if(race_manager->getRaceMode()==RaceManager::RM_FOLLOW_LEADER && i==0)
{
font_race->PrintShadow(_("Leader"), 30, ICON_PLAYER_WIDHT+x, y+5,
255, 0, 0);
} }
glEnable(GL_CULL_FACE); glEnable(GL_CULL_FACE);

View File

@ -58,7 +58,8 @@ Kart::Kart (const std::string& kart_name, int position_ ,
#endif #endif
{ {
m_kart_properties = kart_properties_manager->getKart(kart_name); m_kart_properties = kart_properties_manager->getKart(kart_name);
m_grid_position = position_ ; m_grid_position = position_;
m_initial_position = position_;
m_num_herrings_gobbled = 0; m_num_herrings_gobbled = 0;
m_eliminated = false; m_eliminated = false;
m_finished_race = false; m_finished_race = false;

View File

@ -51,14 +51,14 @@ class Smoke;
class Kart : public TerrainInfo, public Moveable class Kart : public TerrainInfo, public Moveable
{ {
protected: protected:
bool m_on_road; //true if the kart is on top of the bool m_on_road; // true if the kart is on top of the
//road path drawn by the drivelines // road path drawn by the drivelines
Attachment m_attachment; Attachment m_attachment;
Collectable m_collectable; Collectable m_collectable;
int m_grid_position; int m_grid_position;
int m_race_position; int m_race_position; // current race position (1-numKarts)
int m_initial_position; // initial position of kart
KartControl m_controls; // The position of the karts controls KartControl m_controls; // The position of the karts controls
int m_track_sector; // index in driveline, special values int m_track_sector; // index in driveline, special values
// e.g. UNKNOWN_SECTOR can be negative! // e.g. UNKNOWN_SECTOR can be negative!
@ -142,7 +142,8 @@ public:
int getNumCollectables () const { return m_collectable.getNum();} int getNumCollectables () const { return m_collectable.getNum();}
int getNumHerring () const { return m_num_herrings_gobbled;} int getNumHerring () const { return m_num_herrings_gobbled;}
int getLap () const { return m_race_lap; } int getLap () const { return m_race_lap; }
int getPosition () const { return m_race_position ; } int getPosition () const { return m_race_position; }
int getInitialPosition () const { return m_initial_position; }
void setFinishingState(float time); void setFinishingState(float time);
float getFinishTime () const { return m_finish_time; } float getFinishTime () const { return m_finish_time; }
bool raceIsFinished () const { return m_finished_race; } bool raceIsFinished () const { return m_finished_race; }

View File

@ -126,6 +126,16 @@ void DefaultRobot::handle_wheelie( const int STEPS )
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void DefaultRobot::handle_braking() void DefaultRobot::handle_braking()
{ {
// 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)
if(race_manager->getRaceMode()==RaceManager::RM_FOLLOW_LEADER &&
getPosition()<world->getKart(0)->getPosition() &&
getInitialPosition()>1 )
{
printf("kart %s: braking",this->getName().c_str());
m_controls.brake = true;
return;
}
const float MIN_SPEED = world->m_track->getWidth()[m_track_sector]; const float MIN_SPEED = world->m_track->getWidth()[m_track_sector];
//We may brake if we are about to get out of the road, but only if the //We may brake if we are about to get out of the road, but only if the

View File

@ -94,26 +94,27 @@ World::World()
loadTrack() ; loadTrack() ;
int playerIndex = 0; int playerIndex = 0;
for(unsigned int position=0; position<race_manager->getNumKarts(); position++) for(unsigned int i=0; i<race_manager->getNumKarts(); i++)
{ {
int position = i+1; // position start with 1
sgCoord init_pos; sgCoord init_pos;
m_track->getStartCoords(position, &init_pos); m_track->getStartCoords(i, &init_pos);
Kart* newkart; Kart* newkart;
const std::string& kart_name=race_manager->getKartName(position); const std::string& kart_name=race_manager->getKartName(i);
if(user_config->m_profile) if(user_config->m_profile)
{ {
// In profile mode, load only the old kart // In profile mode, load only the old kart
newkart = new DefaultRobot(kart_name, position, init_pos); newkart = new DefaultRobot(kart_name, position, init_pos);
// Create a camera for the last kart (since this way more of the // Create a camera for the last kart (since this way more of the
// karts can be seen. // karts can be seen.
if(position==race_manager->getNumKarts()-1) if(i==race_manager->getNumKarts()-1)
{ {
scene->createCamera(race_manager->getNumPlayers(), playerIndex); scene->createCamera(race_manager->getNumPlayers(), playerIndex);
} }
} }
else else
{ {
if (race_manager->isPlayer(position)) if (race_manager->isPlayer(i))
{ {
Camera *cam = scene->createCamera(race_manager->getNumPlayers(), playerIndex); Camera *cam = scene->createCamera(race_manager->getNumPlayers(), playerIndex);
// the given position belongs to a player // the given position belongs to a player
@ -130,7 +131,7 @@ World::World()
} // if !user_config->m_profile } // if !user_config->m_profile
if(user_config->m_replay_history) if(user_config->m_replay_history)
{ {
history->LoadKartData(newkart, position); history->LoadKartData(newkart, i);
} }
newkart -> getModelTransform() -> clrTraversalMaskBits(SSGTRAV_ISECT|SSGTRAV_HOT); newkart -> getModelTransform() -> clrTraversalMaskBits(SSGTRAV_ISECT|SSGTRAV_HOT);
@ -306,7 +307,7 @@ void World::update(float dt)
for ( Karts::size_type i = 0 ; i < m_kart.size(); ++i) for ( Karts::size_type i = 0 ; i < m_kart.size(); ++i)
{ {
if(!m_kart[i]) continue; // ignore eliminated kart if(m_kart[i]->isEliminated()) continue; // ignore eliminated kart
if(!m_kart[i]->raceIsFinished()) updateRacePosition((int)i); if(!m_kart[i]->raceIsFinished()) updateRacePosition((int)i);
if(m_kart[i]->isPlayerKart()) m_kart[i]->addMessages(); // add 'wrong direction' if(m_kart[i]->isPlayerKart()) m_kart[i]->addMessages(); // add 'wrong direction'
} }
@ -465,14 +466,30 @@ void World::updateRaceStatus(float dt)
m_leader_intervals.erase(m_leader_intervals.begin()); m_leader_intervals.erase(m_leader_intervals.begin());
m_clock=m_leader_intervals[0]; m_clock=m_leader_intervals[0];
int kart_number; int kart_number;
// If the leader kart is not the first kart, remove the first
// kart, otherwise remove the last kart.
int position_to_remove = m_kart[0]->getPosition()==1
? getCurrentNumKarts() : 1;
for (kart_number=0; kart_number<(int)m_kart.size(); kart_number++) for (kart_number=0; kart_number<(int)m_kart.size(); kart_number++)
{ {
if(m_kart[kart_number]->isEliminated()) continue; if(m_kart[kart_number]->isEliminated()) continue;
if(m_kart[kart_number]->getPosition()==getCurrentNumKarts()) if(m_kart[kart_number]->getPosition()==position_to_remove)
break; break;
} }
assert(kart_number!=m_kart.size()); if(kart_number==m_kart.size())
removeKart(kart_number); {
fprintf(stderr,"Problem with removing leader: position %d not found\n",
position_to_remove);
for(int i=0; i<(int)m_kart.size(); i++)
{
fprintf(stderr,"kart %d: eliminated %d position %d\n",
i,m_kart[i]->isEliminated(), m_kart[i]->getPosition());
} // for i
} // kart_number==m_kart.size()
else
{
removeKart(kart_number);
}
// The follow the leader race is over if there isonly one kart left, // The follow the leader race is over if there isonly one kart left,
// or if all players have gone // or if all players have gone
if(getCurrentNumKarts()==2 ||getCurrentNumPlayers()==0) if(getCurrentNumKarts()==2 ||getCurrentNumPlayers()==0)
@ -614,12 +631,12 @@ void World::removeKart(int kart_number)
camera->setMode(Camera::CM_LEADER_MODE); camera->setMode(Camera::CM_LEADER_MODE);
m_eliminated_players++; m_eliminated_players++;
} }
projectile_manager->newExplosion(kart->getCoord());
// The kart can't be eliminated, since otherwise a race can't be restarted. // The kart can't be really removed from the m_kart array, since otherwise
// So it's only marked to be eliminated (and ignored in all loops). Important: // a race can't be restarted. So it's only marked to be eliminated (and
// world->getCurrentNumKarts() returns the number of still racing karts. This // ignored in all loops). Important:world->getCurrentNumKarts() returns
// value can not be used for loops over all karts, use race_manager->getNumKarts() // the number of karts still racing. This value can not be used for loops
// instead! // over all karts, use race_manager->getNumKarts() instead!
race_manager->addKartResult(kart_number, kart->getPosition(), m_clock); race_manager->addKartResult(kart_number, kart->getPosition(), m_clock);
race_manager->eliminate(kart_number); race_manager->eliminate(kart_number);
kart->eliminate(); kart->eliminate();
@ -637,7 +654,7 @@ void World::updateRacePosition ( int k )
for ( Karts::size_type j = 0 ; j < m_kart.size() ; ++j ) for ( Karts::size_type j = 0 ; j < m_kart.size() ; ++j )
{ {
if(int(j) == k) continue; if(int(j) == k) continue;
if(!m_kart[j]) continue; // eliminated karts if(m_kart[j]->isEliminated()) continue; // eliminated karts
// Count karts ahead of the current kart, i.e. kart that are already // Count karts ahead of the current kart, i.e. kart that are already
// finished (the current kart k has not yet finished!!), have done more // finished (the current kart k has not yet finished!!), have done more