Improvements to finish time accuracy (#3273)

* Add time info for recent positions

* More accurate finish time

* Rebase changes on the version with overrides
This commit is contained in:
Alayan-stk-2 2018-05-28 00:04:57 +02:00 committed by auriamg
parent 6444405479
commit 670a40cb05
4 changed files with 67 additions and 12 deletions

View File

@ -489,6 +489,9 @@ public:
/** Returns the most recent different previous position */ /** Returns the most recent different previous position */
virtual const Vec3& getRecentPreviousXYZ() const = 0; virtual const Vec3& getRecentPreviousXYZ() const = 0;
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Returns the time at which the recent previous position occured */
virtual const float getRecentPreviousXYZTime() const = 0;
// ------------------------------------------------------------------------
/** Returns the height of the terrain. we're currently above */ /** Returns the height of the terrain. we're currently above */
virtual float getHoT() const = 0; virtual float getHoT() const = 0;
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------

View File

@ -152,6 +152,7 @@ Kart::Kart (const std::string& ident, unsigned int world_kart_id,
for (int i=0;i<m_xyz_history_size;i++) for (int i=0;i<m_xyz_history_size;i++)
{ {
m_previous_xyz.push_back(initial_position); m_previous_xyz.push_back(initial_position);
m_previous_xyz_times.push_back(0.0f);
} }
m_time_previous_counter = 0.0f; m_time_previous_counter = 0.0f;
@ -381,6 +382,7 @@ void Kart::reset()
for (int i=0;i<m_xyz_history_size;i++) for (int i=0;i<m_xyz_history_size;i++)
{ {
m_previous_xyz[i] = getXYZ(); m_previous_xyz[i] = getXYZ();
m_previous_xyz_times[i] = 0.0f;
} }
m_time_previous_counter = 0.0f; m_time_previous_counter = 0.0f;
@ -927,7 +929,9 @@ void Kart::finishedRace(float time, bool from_server)
} // !from_server } // !from_server
m_finished_race = true; m_finished_race = true;
m_finish_time = time; m_finish_time = time;
m_controller->finishedRace(time); m_controller->finishedRace(time);
m_kart_model->finishedRace(); m_kart_model->finishedRace();
race_manager->kartFinishedRace(this, time); race_manager->kartFinishedRace(this, time);
@ -1317,9 +1321,11 @@ void Kart::update(int ticks)
while (m_time_previous_counter > stk_config->ticks2Time(1)) while (m_time_previous_counter > stk_config->ticks2Time(1))
{ {
m_previous_xyz[0] = getXYZ(); m_previous_xyz[0] = getXYZ();
m_previous_xyz_times[0] = World::getWorld()->getTime();
for (int i=m_xyz_history_size-1;i>0;i--) for (int i=m_xyz_history_size-1;i>0;i--)
{ {
m_previous_xyz[i] = m_previous_xyz[i-1]; m_previous_xyz[i] = m_previous_xyz[i-1];
m_previous_xyz_times[i] = m_previous_xyz_times[i-1];
} }
m_time_previous_counter -= stk_config->ticks2Time(1); m_time_previous_counter -= stk_config->ticks2Time(1);
} }
@ -3132,6 +3138,13 @@ const Vec3& Kart::getRecentPreviousXYZ() const
return m_previous_xyz[m_xyz_history_size/5]; return m_previous_xyz[m_xyz_history_size/5];
} // getRecentPreviousXYZ } // getRecentPreviousXYZ
// ------------------------------------------------------------------------
/** Returns the time at which the recent previoux position occured */
const float Kart::getRecentPreviousXYZTime() const
{
return m_previous_xyz_times[m_xyz_history_size/5];
} // getRecentPreviousXYZTime
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void Kart::playSound(SFXBuffer* buffer) void Kart::playSound(SFXBuffer* buffer)
{ {

View File

@ -84,6 +84,10 @@ protected:
/** The coordinates of the XYZ_HISTORY_SIZE previous positions */ /** The coordinates of the XYZ_HISTORY_SIZE previous positions */
std::vector<Vec3> m_previous_xyz; std::vector<Vec3> m_previous_xyz;
/** The times at which the previous positions occured.
Currently used for finish time computation */
std::vector<float> m_previous_xyz_times;
float m_time_previous_counter; float m_time_previous_counter;
/** Is time flying activated */ /** Is time flying activated */
@ -519,6 +523,9 @@ public:
/** Returns a more recent different previous position */ /** Returns a more recent different previous position */
virtual const Vec3& getRecentPreviousXYZ() const OVERRIDE; virtual const Vec3& getRecentPreviousXYZ() const OVERRIDE;
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Returns the time at which the recent previous position occured */
virtual const float getRecentPreviousXYZTime() const;
// ------------------------------------------------------------------------
/** For debugging only: check if a kart is flying. */ /** For debugging only: check if a kart is flying. */
bool isFlying() const { return m_flying; } bool isFlying() const { return m_flying; }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------

View File

@ -157,10 +157,6 @@ void LinearWorld::reset()
*/ */
void LinearWorld::update(int ticks) void LinearWorld::update(int ticks)
{ {
// run generic parent stuff that applies to all modes. It
// especially updates the kart positions.
WorldWithRank::update(ticks);
const unsigned int kart_amount = getNumKarts(); const unsigned int kart_amount = getNumKarts();
// Do stuff specific to this subtype of race. // Do stuff specific to this subtype of race.
@ -189,6 +185,11 @@ void LinearWorld::update(int ticks)
+ getDistanceDownTrackForKart(kart->getWorldKartId(), true); + getDistanceDownTrackForKart(kart->getWorldKartId(), true);
} // for n } // for n
// Run generic parent stuff that applies to all modes.
// It especially updates the kart positions.
// It MUST be done after the update of the distances
WorldWithRank::update(ticks);
// Update all positions. This must be done after _all_ karts have // Update all positions. This must be done after _all_ karts have
// updated their position and laps etc, otherwise inconsistencies // updated their position and laps etc, otherwise inconsistencies
// (like two karts at same position) can occur. // (like two karts at same position) can occur.
@ -409,9 +410,37 @@ void LinearWorld::newLap(unsigned int kart_index)
updateRacePosition(); updateRacePosition();
// Race finished // Race finished
// We compute the exact moment the kart crossed the line
// This way, even with poor framerate, we get a time significant to the ms
if(kart_info.m_finished_laps >= race_manager->getNumLaps() && raceHasLaps()) if(kart_info.m_finished_laps >= race_manager->getNumLaps() && raceHasLaps())
{ {
kart->finishedRace(getTime()); if (kart->isGhostKart())
{
GhostKart* gk = dynamic_cast<GhostKart*>(kart);
// Old replays don't store distance, so don't use the ghost method
// Ghosts also don't store the previous positions, so the method
// for normal karts can't be used.
if (gk->getGhostFinishTime() > 0.0f)
kart->finishedRace(gk->getGhostFinishTime());
else
kart->finishedRace(getTime());
}
else
{
float curr_distance_after_line = getDistanceDownTrackForKart(kart->getWorldKartId(),false);
TrackSector prev_sector;
prev_sector.update(kart->getRecentPreviousXYZ());
float prev_distance_before_line = Track::getCurrentTrack()->getTrackLength()
- prev_sector.getDistanceFromStart(false);
float finish_proportion = curr_distance_after_line
/ (prev_distance_before_line + curr_distance_after_line);
float prev_time = kart->getRecentPreviousXYZTime();
float finish_time = prev_time*finish_proportion + getTime()*(1.0f-finish_proportion);
kart->finishedRace(finish_time);
}
} }
int ticks_per_lap; int ticks_per_lap;
if (kart_info.m_finished_laps == 1) // just completed first lap if (kart_info.m_finished_laps == 1) // just completed first lap
@ -626,7 +655,10 @@ float LinearWorld::estimateFinishTimeForKart(AbstractKart* kart)
if (kart->isGhostKart()) if (kart->isGhostKart())
{ {
GhostKart* gk = dynamic_cast<GhostKart*>(kart); GhostKart* gk = dynamic_cast<GhostKart*>(kart);
return gk->getGhostFinishTime(); // Old replays don't store distance, so don't use the ghost method
// They'll return a negative time here
if (gk->getGhostFinishTime() > 0.0f)
return gk->getGhostFinishTime();
} }
if(full_distance == 0) if(full_distance == 0)
@ -660,22 +692,22 @@ float LinearWorld::estimateFinishTimeForKart(AbstractKart* kart)
// Avoid NAN or invalid results when average_speed is very low // Avoid NAN or invalid results when average_speed is very low
// or negative (which can happen if a kart drives backwards and // or negative (which can happen if a kart drives backwards and
// m_overall distance becomes smaller than -m_distance_increase). // m_overall distance becomes smaller than -m_distance_increase).
// In this case set the time to 99 minutes, offset by kart // In this case set the time to 59 minutes, offset by kart
// position (to spread arrival times for all karts that arrive // position (to spread arrival times for all karts that arrive
// even later). This works for up to 60 karts (otherwise the // even later). This works for up to 60 karts (otherwise the
// time displayed would become too long: 100:xx:yy). // time displayed would overflow to 00:yy).
if(average_speed<0.01f) if(average_speed<0.01f)
return 99*60.0f + kart->getPosition(); return 59*60.0f + kart->getPosition();
float est_time = getTime() + (full_distance - kart_info.m_overall_distance) float est_time = getTime() + (full_distance - kart_info.m_overall_distance)
/ average_speed; / average_speed;
// Avoid times > 99:00 - in this case use kart position to spread // Avoid times > 59:00 - in this case use kart position to spread
// arrival time so that each kart has a unique value. The pre-condition // arrival time so that each kart has a unique value. The pre-condition
// guarantees that this works correctly (higher position -> less distance // guarantees that this works correctly (higher position -> less distance
// covered -> later arrival time). // covered -> later arrival time).
if(est_time>99*60.0f) if(est_time>59*60.0f)
return 99*60.0f + kart->getPosition(); return 59*60.0f + kart->getPosition();
return est_time; return est_time;
} // estimateFinishTimeForKart } // estimateFinishTimeForKart