1) Added a better estimation of finishing time for karts that

didn't finish, based on the up-to-now average speed.
2) Changed the race result display to display all results 
   (and not to ignore the last entry).
3) The race will not finish if the last kart racing
   and not arriving in time is a player kart.
4) Made world->m_clock private and added getter function.


git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/trunk/supertuxkart@1449 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk
2008-02-08 04:43:35 +00:00
parent d7057c7980
commit 8bc9fd0286
13 changed files with 65 additions and 63 deletions

View File

@@ -22,7 +22,7 @@
#define MAX_HISTORY 50000 /* number of history events */
#define TIME_DELAY_TILL_FINISH 10.0f /* time after all player karts finish */
#define TIME_DELAY_TILL_FINISH 0.100f /* time after all player karts finish */
/*
All final units are in meters (or meters/sec or meters/sec^2)
and degrees (or degrees/sec).

View File

@@ -87,7 +87,7 @@ void GameManager::run()
if(user_config->m_profile)
{
m_frame_count++;
if (world->m_clock>user_config->m_profile)
if (world->getTime()>user_config->m_profile)
{
//FIXME: SDL_GetTicks() includes the loading time,
//so the FPS will be skewed for now.

View File

@@ -263,7 +263,7 @@ void RaceGUI::drawTimer ()
char str[256];
assert(world != NULL);
m_time_left = world->m_clock;
m_time_left = world->getTime();
TimeToString(m_time_left, str);
#ifdef USE_WIDGET_MANAGER
@@ -410,7 +410,7 @@ void RaceGUI::drawPlayerIcons ()
glDisable(GL_CULL_FACE);
if(laps_of_leader>0 && // Display position during first lap
(world->m_clock - kart->getTimeAtLap()<5.0f ||
(world->getTime() - kart->getTimeAtLap()<5.0f ||
lap!=laps_of_leader))
{ // Display for 5 seconds
char str[256];
@@ -422,7 +422,7 @@ void RaceGUI::drawPlayerIcons ()
else
{
float timeBehind;
timeBehind = (lap==laps_of_leader ? kart->getTimeAtLap() : world->m_clock)
timeBehind = (lap==laps_of_leader ? kart->getTimeAtLap() : world->getTime())
- time_of_leader;
str[0]='+'; str[1]=0;
TimeToString(timeBehind, str+1);

View File

@@ -55,10 +55,10 @@ class RaceGUI: public BaseGUI
m_message = message;
m_font_size = size;
m_kart = kart;
m_end_time = time>=0.0f ? world->m_clock+time : -1.0f;
m_end_time = time>=0.0f ? world->getTime()+time : -1.0f;
m_red=red; m_blue=blue; m_green=green;
}
bool done() const {return m_end_time<0 || world->m_clock>m_end_time;}
bool done() const {return m_end_time<0 || world->getTime()>m_end_time;}
};
public:

View File

@@ -93,15 +93,9 @@ RaceResultsGUI::RaceResultsGUI()
const Kart *KART = world->getKart(order[i]);
const std::string& KART_NAME = KART->getName();
char sTime[20];
if(i==NUM_KARTS-1 && world->m_race_setup.m_mode!=RaceSetup::RM_TIME_TRIAL)
{
sprintf(sTime," ");
}
else
{
const float T = KART->getFinishTime();
TimeToString(T, sTime);
}
const float T = KART->getFinishTime();
TimeToString(T, sTime);
//This shows position + driver name + time + points earned + total points
if(world->m_race_setup.m_mode==RaceSetup::RM_GRAND_PRIX)
{

View File

@@ -69,7 +69,7 @@ void Herring::update(float delta)
{
if(m_eaten)
{
const float T = m_time_to_return - world->m_clock;
const float T = m_time_to_return - world->getTime();
if ( T > 0 )
{
sgVec3 hell;
@@ -99,6 +99,6 @@ void Herring::update(float delta)
void Herring::isEaten()
{
m_eaten=true;
m_time_to_return=world->m_clock+2.0f;
m_time_to_return=world->getTime()+2.0f;
}

View File

@@ -409,23 +409,23 @@ void Kart::doLapCounting ()
// will begin another countdown).
if(m_race_lap+1<=world->m_race_setup.m_num_laps)
{
setTimeAtLap(world->m_clock);
setTimeAtLap(world->getTime());
m_race_lap++ ;
}
m_shortcut_count = 0;
// Only do timings if original time was set properly. Driving backwards
// over the start line will cause the lap start time to be set to 0.
// over the start line will cause the lap start time to be set to -1.
if(m_lap_start_time>=0.0)
{
float time_per_lap;
if (m_race_lap == 1) // just completed first lap
{
time_per_lap=world->m_clock;
time_per_lap=world->getTime();
}
else //completing subsequent laps
{
time_per_lap=world->m_clock-m_lap_start_time;
time_per_lap=world->getTime()-m_lap_start_time;
}
if(time_per_lap < world->getFastestLapTime() )
@@ -450,7 +450,7 @@ void Kart::doLapCounting ()
//printf("Time per lap: %s %f\n", getName().c_str(), time_per_lap);
}
}
m_lap_start_time = world->m_clock;
m_lap_start_time = world->getTime();
}
else if ( newLap )
{
@@ -1201,6 +1201,29 @@ void Kart::setFinishingState(float time)
{
m_finished_race = true;
m_finish_time = time;
}
} // setFinishingState
//-----------------------------------------------------------------------------
float Kart::estimateFinishTime ()
{
// Estimate the arrival time of any karts that haven't arrived
// yet by using their average speed up to now and the distance
// still to race. This approach guarantees that the order of
// the karts won't change anymore (karts ahead will have a
// higher average speed and therefore finish the race earlier
// than karts further behind), so the position doesn't have to
// be updated to get the correct scoring.
float distance_covered = getLap()*world->m_track->getTrackLength()
+ getDistanceDownTrack();
// In case that a kart is rescued behind start line, or ...
if(distance_covered<0) distance_covered =1.0f;
float average_speed = distance_covered/world->getTime();
// Finish time is the time needed for the whole race with
// the average speed computed above.
return world->m_race_setup.m_num_laps*world->m_track->getTrackLength()
/ average_speed;
} // estimateFinishTime
/* EOF */

View File

@@ -170,6 +170,7 @@ public:
bool isTakingShortcut () const { return m_shortcut_type!=SC_NONE;}
bool raceIsFinished () const { return m_finished_race; }
void endRescue ();
float estimateFinishTime ();
void processSkidMarks ();
void getClosestKart (float *cdist, int *closest);
void updatePhysics (float dt);

View File

@@ -88,7 +88,7 @@ void MovingTexture::update(float dt)
sgCoord add;
float timer = world->m_clock + m_phase ;
float timer = world->getTime() + m_phase ;
if ( m_cycle != 0.0 && m_mode != MODE_FORWARD )
{

View File

@@ -172,10 +172,10 @@ void PlayerKart::crashed()
// noise by playing the crash sound over and over again. To prevent
// this, the crash sound is only played if there was at least 0.5
// seconds since the last time it was played (for this kart)
if(world->m_clock - m_time_last_crash_sound > 0.5f)
if(world->getTime() - m_time_last_crash_sound > 0.5f)
{
sound_manager->playSfx( SOUND_CRASH );
m_time_last_crash_sound = world->m_clock;
m_time_last_crash_sound = world->getTime();
}
} // crashed

View File

@@ -62,7 +62,7 @@ bool ReplayRecorder::pushFrame()
if( m_ReplayBuffers.getNumberFrames() )
{
ReplayFrame const *last_Frame = m_ReplayBuffers.getFrameAt( m_ReplayBuffers.getNumberFrames() - 1 );
if( (world->getClock() - last_Frame->time) < REPLAY_TIME_STEP_MIN ) return true;
if( (world->getTime() - last_Frame->time) < REPLAY_TIME_STEP_MIN ) return true;
}
ReplayFrame *pFrame = getNewFrame();

View File

@@ -423,7 +423,6 @@ bool World::loadReplayHumanReadable( std::string const &filename )
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void World::checkRaceStatus()
{
if (m_clock > 1.0 && m_ready_set_go == 0)
@@ -459,6 +458,7 @@ void World::checkRaceStatus()
int new_finished_karts = 0;
for ( Karts::size_type i = 0; i < m_kart.size(); ++i)
{
// FIXME: this part should be done as part of Kart::update
if ((m_kart[i]->getLap () >= m_race_setup.m_num_laps) && !m_kart[i]->raceIsFinished())
{
m_kart[i]->setFinishingState(m_clock);
@@ -482,19 +482,25 @@ void World::checkRaceStatus()
}
}
race_manager->addFinishedKarts(new_finished_karts);
// Different ending conditions:
// 1) all players are finished -->
// wait TIME_DELAY_TILL_FINISH seconds - if no other end condition
// applies, end the game (and make up some artificial times for the
// outstanding karts).
// 2) If only one kart is playing, finish when one kart is finished.
// 3) Otherwise, wait till all karts except one is finished - the last
// kart obviously becoming the last
if(race_manager->allPlayerFinished() && m_phase == RACE_PHASE)
// 1) All karts are finished --> end the race
// ==========================================
if(race_manager->getFinishedKarts() >= m_race_setup.getNumKarts() )
{
m_phase = FINISH_PHASE;
}
// 2) All player karts are finished --> wait some
// time for AI karts to arrive before finishing
// ===============================================
else if(race_manager->allPlayerFinished() && m_phase == RACE_PHASE)
{
m_phase = DELAY_FINISH_PHASE;
m_finish_delay_start_time = m_clock;
}
// 3) If the 'wait for AI' time is over, estimate arrival times & finish
// =====================================================================
else if(m_phase==DELAY_FINISH_PHASE &&
m_clock-m_finish_delay_start_time>TIME_DELAY_TILL_FINISH)
{
@@ -503,32 +509,11 @@ void World::checkRaceStatus()
{
if(!m_kart[i]->raceIsFinished())
{
// FIXME: Add some tenths to have different times - a better solution
// would be to estimate the distance to go and use this to
// determine better times.
m_kart[i]->setFinishingState(m_clock+m_kart[i]->getPosition()*0.3f);
m_kart[i]->setFinishingState(m_kart[i]->estimateFinishTime());
race_manager->addKartScore((int)i, m_kart[i]->getPosition());
} // if !raceIsFinished
} // for i
}
else if(m_race_setup.getNumKarts() == 1)
{
if(race_manager->getFinishedKarts() == 1) m_phase = FINISH_PHASE;
}
else if(race_manager->getFinishedKarts() >= m_race_setup.getNumKarts() - 1)
{
m_phase = FINISH_PHASE;
for ( Karts::size_type i = 0; i < m_kart.size(); ++i)
{
if(!m_kart[i]->raceIsFinished())
{
m_kart[i]->setFinishingState(m_clock);
} // if !raceIsFinished
} // for i
} // if getFinishedKarts()>=geNumKarts()
} // checkRaceStatus
//-----------------------------------------------------------------------------

View File

@@ -39,7 +39,6 @@ class World
{
public:
typedef std::vector<Kart*> Karts;
float m_clock;
/** resources, this should be put in a separate class or replaced by a smart
* resource manager
@@ -97,6 +96,7 @@ public:
float getFastestLapTime() const { return m_fastest_lap; }
void setFastestLap(Kart *k, float time) {m_fastest_kart=k;m_fastest_lap=time;}
const Highscores* getHighscores() const { return m_highscores; }
float getTime() const { return m_clock; }
void pause();
void unpause();
@@ -108,6 +108,7 @@ private:
Kart* m_fastest_kart;
Highscores* m_highscores;
Phase m_phase;
float m_clock;
void updateRacePosition( int k );
void loadTrack();
@@ -117,8 +118,6 @@ private:
sgCoord init_pos);
#ifdef HAVE_GHOST_REPLAY
public:
float getClock() const { return m_clock; }
private:
bool saveReplayHumanReadable( std::string const &filename ) const;
bool loadReplayHumanReadable( std::string const &filename );