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 */
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 */
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++)
{
m_previous_xyz.push_back(initial_position);
m_previous_xyz_times.push_back(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++)
{
m_previous_xyz[i] = getXYZ();
m_previous_xyz_times[i] = 0.0f;
}
m_time_previous_counter = 0.0f;
@ -927,7 +929,9 @@ void Kart::finishedRace(float time, bool from_server)
} // !from_server
m_finished_race = true;
m_finish_time = time;
m_controller->finishedRace(time);
m_kart_model->finishedRace();
race_manager->kartFinishedRace(this, time);
@ -1317,9 +1321,11 @@ void Kart::update(int ticks)
while (m_time_previous_counter > stk_config->ticks2Time(1))
{
m_previous_xyz[0] = getXYZ();
m_previous_xyz_times[0] = World::getWorld()->getTime();
for (int i=m_xyz_history_size-1;i>0;i--)
{
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);
}
@ -3132,6 +3138,13 @@ const Vec3& Kart::getRecentPreviousXYZ() const
return m_previous_xyz[m_xyz_history_size/5];
} // 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)
{

View File

@ -84,6 +84,10 @@ protected:
/** The coordinates of the XYZ_HISTORY_SIZE previous positions */
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;
/** Is time flying activated */
@ -519,6 +523,9 @@ public:
/** Returns a more recent different previous position */
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. */
bool isFlying() const { return m_flying; }
// ------------------------------------------------------------------------

View File

@ -157,10 +157,6 @@ void LinearWorld::reset()
*/
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();
// Do stuff specific to this subtype of race.
@ -189,6 +185,11 @@ void LinearWorld::update(int ticks)
+ getDistanceDownTrackForKart(kart->getWorldKartId(), true);
} // 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
// updated their position and laps etc, otherwise inconsistencies
// (like two karts at same position) can occur.
@ -409,9 +410,37 @@ void LinearWorld::newLap(unsigned int kart_index)
updateRacePosition();
// 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())
{
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;
if (kart_info.m_finished_laps == 1) // just completed first lap
@ -626,7 +655,10 @@ float LinearWorld::estimateFinishTimeForKart(AbstractKart* kart)
if (kart->isGhostKart())
{
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)
@ -660,22 +692,22 @@ float LinearWorld::estimateFinishTimeForKart(AbstractKart* kart)
// Avoid NAN or invalid results when average_speed is very low
// or negative (which can happen if a kart drives backwards and
// 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
// 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)
return 99*60.0f + kart->getPosition();
return 59*60.0f + kart->getPosition();
float est_time = getTime() + (full_distance - kart_info.m_overall_distance)
/ 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
// guarantees that this works correctly (higher position -> less distance
// covered -> later arrival time).
if(est_time>99*60.0f)
return 99*60.0f + kart->getPosition();
if(est_time>59*60.0f)
return 59*60.0f + kart->getPosition();
return est_time;
} // estimateFinishTimeForKart