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:
@@ -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).
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
35
src/kart.cpp
35
src/kart.cpp
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 )
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@@ -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 );
|
||||
|
||||
Reference in New Issue
Block a user