Fixed rewind (events had a time stamp after increasing world clock,

while states had a time stamp before world clock was updated).
Still all work in progress ;)


git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/rewind@14138 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk 2013-09-23 06:57:32 +00:00
parent cb46fad124
commit 891df54f3a
5 changed files with 68 additions and 46 deletions

View File

@ -52,8 +52,9 @@
#include "karts/max_speed.hpp" #include "karts/max_speed.hpp"
#include "karts/skidding.hpp" #include "karts/skidding.hpp"
#include "modes/linear_world.hpp" #include "modes/linear_world.hpp"
#include "network/race_state.hpp"
#include "network/network_manager.hpp" #include "network/network_manager.hpp"
#include "network/rewind_manager.hpp"
#include "network/race_state.hpp"
#include "physics/btKart.hpp" #include "physics/btKart.hpp"
#include "physics/btKartRaycast.hpp" #include "physics/btKartRaycast.hpp"
#include "physics/btUprightConstraint.hpp" #include "physics/btUprightConstraint.hpp"
@ -530,7 +531,7 @@ void Kart::blockViewWithPlunger()
if(isShielded()) if(isShielded())
{ {
decreaseShieldTime(0.0f); //decrease the default amount of time decreaseShieldTime(0.0f); //decrease the default amount of time
Log::verbose("Kart", "Decreasing shield, because of removing the plunger. \n"); Log::verbose("Kart", "Decreasing shield, because of removing the plunger.");
} }
} // blockViewWithPlunger } // blockViewWithPlunger
@ -1088,7 +1089,7 @@ void Kart::update(float dt)
// Update the position and other data taken from the physics // Update the position and other data taken from the physics
Moveable::update(dt); Moveable::update(dt);
if(!history->replayHistory()) if(!history->replayHistory() && !RewindManager::get()->isRewinding())
m_controller->update(dt); m_controller->update(dt);
// if its view is blocked by plunger, decrease remaining time // if its view is blocked by plunger, decrease remaining time
@ -1362,7 +1363,7 @@ void Kart::setSquash(float time, float slowdown)
if (isShielded()) if (isShielded())
{ {
decreaseShieldTime(stk_config->m_bubblegum_shield_time/2.0f); decreaseShieldTime(stk_config->m_bubblegum_shield_time/2.0f);
Log::verbose("Kart", "Decreasing shield \n"); Log::verbose("Kart", "Decreasing shield");
return; return;
} }
@ -2043,7 +2044,7 @@ void Kart::updatePhysics(float dt)
); );
#endif #endif
} // updatePhysics } // updatephysics
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** Adjust the engine sound effect depending on the speed of the kart. /** Adjust the engine sound effect depending on the speed of the kart.

View File

@ -93,7 +93,7 @@ void KartRewinder::update()
m_previous_control.copyToMemory(buffer); m_previous_control.copyToMemory(buffer);
// The rewind manager will free the memory once it's not needed anymore // The rewind manager will free the memory once it's not needed anymore
RewindManager::get()->addEvent(this, World::getWorld()->getTime(), buffer); RewindManager::get()->addEvent(this, buffer);
} // update } // update
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

View File

@ -827,11 +827,12 @@ void World::update(float dt)
if(ReplayRecorder::get()) ReplayRecorder::get()->update(dt); if(ReplayRecorder::get()) ReplayRecorder::get()->update(dt);
if(ReplayPlay::get()) ReplayPlay::get()->update(dt); if(ReplayPlay::get()) ReplayPlay::get()->update(dt);
if(history->replayHistory()) dt=history->getNextDelta(); if(history->replayHistory()) dt=history->getNextDelta();
WorldStatus::update(dt);
// Clear race state so that new information can be stored // Clear race state so that new information can be stored
race_state->clear(); race_state->clear();
RewindManager::get()->saveStates(dt); RewindManager::get()->setCurrentTime(World::getWorld()->getTime(), dt);
RewindManager::get()->saveStates();
WorldStatus::update(dt);
if(network_manager->getMode()!=NetworkManager::NW_CLIENT && if(network_manager->getMode()!=NetworkManager::NW_CLIENT &&

View File

@ -49,12 +49,12 @@ void RewindManager::destroy()
* for all state info. * for all state info.
* \param size Necessary buffer size for a state. * \param size Necessary buffer size for a state.
*/ */
RewindManager::RewindInfo::RewindInfo(Rewinder *rewinder, float time, RewindManager::RewindInfo::RewindInfo(Rewinder *rewinder, char *buffer,
char *buffer, bool is_event, bool is_event, bool is_confirmed)
bool is_confirmed)
{ {
m_rewinder = rewinder; m_rewinder = rewinder;
m_time = time; m_time = RewindManager::get()->getCurrentTime();;
m_time_step = RewindManager::get()->getCurrentTimeStep();
m_local_physics_time = World::getWorld()->getPhysics()->getPhysicsWorld()->getLocalTime(); m_local_physics_time = World::getWorld()->getPhysics()->getPhysicsWorld()->getLocalTime();
m_buffer = buffer; m_buffer = buffer;
m_type = is_event ? RIT_EVENT : RIT_STATE; m_type = is_event ? RIT_EVENT : RIT_STATE;
@ -62,10 +62,11 @@ RewindManager::RewindInfo::RewindInfo(Rewinder *rewinder, float time,
} // RewindInfo } // RewindInfo
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
RewindManager::RewindInfo::RewindInfo(float time) RewindManager::RewindInfo::RewindInfo()
{ {
m_rewinder = NULL; m_rewinder = NULL;
m_time = time; m_time = RewindManager::get()->getCurrentTime();
m_time_step = RewindManager::get()->getCurrentTimeStep();
m_local_physics_time = World::getWorld()->getPhysics()->getPhysicsWorld()->getLocalTime(); m_local_physics_time = World::getWorld()->getPhysics()->getPhysicsWorld()->getLocalTime();
m_buffer = NULL; m_buffer = NULL;
m_type = RIT_TIME; m_type = RIT_TIME;
@ -220,10 +221,10 @@ unsigned int RewindManager::findFirstIndex(float target_time) const
* \param time Time at which the event was recorded. * \param time Time at which the event was recorded.
* \param buffer Pointer to the event data. * \param buffer Pointer to the event data.
*/ */
void RewindManager::addEvent(Rewinder *rewinder, float time, char *buffer) void RewindManager::addEvent(Rewinder *rewinder, char *buffer)
{ {
if(m_is_rewinding) return; if(m_is_rewinding) return;
RewindInfo *ri = new RewindInfo(rewinder, time, buffer, /*is_event*/true, RewindInfo *ri = new RewindInfo(rewinder, buffer, /*is_event*/true,
/*is_confirmed*/true); /*is_confirmed*/true);
insertRewindInfo(ri); insertRewindInfo(ri);
} // addEvent } // addEvent
@ -233,7 +234,7 @@ void RewindManager::addEvent(Rewinder *rewinder, float time, char *buffer)
* rewinder to do so. * rewinder to do so.
* \param dt Time step size. * \param dt Time step size.
*/ */
void RewindManager::saveStates(float dt) void RewindManager::saveStates()
{ {
if(!m_enable_rewind_manager || if(!m_enable_rewind_manager ||
m_all_rewinder.size()==0 || m_all_rewinder.size()==0 ||
@ -242,7 +243,7 @@ void RewindManager::saveStates(float dt)
float time = World::getWorld()->getTime(); float time = World::getWorld()->getTime();
if(time - m_last_saved_state < m_state_frequency) if(time - m_last_saved_state < m_state_frequency)
{ {
RewindInfo *ri = new RewindInfo(World::getWorld()->getTime()); RewindInfo *ri = new RewindInfo();
insertRewindInfo(ri); insertRewindInfo(ri);
return; return;
} }
@ -255,7 +256,7 @@ void RewindManager::saveStates(float dt)
if(size>=0) if(size>=0)
{ {
m_overall_state_size += size; m_overall_state_size += size;
RewindInfo *ri = new RewindInfo(m_all_rewinder[i], time, p, RewindInfo *ri = new RewindInfo(m_all_rewinder[i], p,
/*is_event*/false, /*is_event*/false,
/*is_confirmed*/true); /*is_confirmed*/true);
assert(ri); assert(ri);
@ -324,11 +325,6 @@ void RewindManager::rewindTo(float rewind_time)
// current time. // current time.
// TODO: this assumes atm that all rewinder have a initial state // TODO: this assumes atm that all rewinder have a initial state
// for 'current_time'!!! // for 'current_time'!!!
while(m_rewind_info[state]->getTime()==exact_rewind_time)
{
m_rewind_info[state]->rewind();
state ++;
} // while rewind info at time current_time
// Store the time to which we have to replay to // Store the time to which we have to replay to
float current_time = World::getWorld()->getTime(); float current_time = World::getWorld()->getTime();
@ -337,27 +333,15 @@ void RewindManager::rewindTo(float rewind_time)
// Now go forward through the saved states, and // Now go forward through the saved states, and
// replay taking the events into account. // replay taking the events into account.
while(World::getWorld()->getTime() < current_time && while( World::getWorld()->getTime() < current_time &&
state < (int)m_rewind_info.size()) state < (int)m_rewind_info.size() )
{ {
// Find the next RewindInfo which needs to be taken into account
// All other states can be deleted
// TODO ... for now
int next_important_state = state;
while(next_important_state < (int)m_rewind_info.size() &&
m_rewind_info[next_important_state]->isState() &&
!m_rewind_info[next_important_state]->isConfirmed() )
{
// TODO discard/replace state
next_important_state ++;
}
float dt = determineTimeStepSize(state, current_time); float dt = determineTimeStepSize(state, current_time);
float next_time = World::getWorld()->getTime() + dt;
// Now set all events and confirmed states // Now set all events and confirmed states
while(state < (int)m_rewind_info.size() && while(state < (int)m_rewind_info.size() &&
m_rewind_info[state]->getTime() <= next_time) m_rewind_info[state]->getTime()<=World::getWorld()->getTime()+0.001f)
{ {
if(m_rewind_info[state]->isEvent() || if(m_rewind_info[state]->isEvent() ||
m_rewind_info[state]->isConfirmed() ) m_rewind_info[state]->isConfirmed() )
@ -388,6 +372,8 @@ void RewindManager::rewindTo(float rewind_time)
*/ */
float RewindManager::determineTimeStepSize(int next_state, float end_time) float RewindManager::determineTimeStepSize(int next_state, float end_time)
{ {
return m_rewind_info[next_state]->getTimeStep();
return m_rewind_info[next_state]->getTime()-World::getWorld()->getTime(); return m_rewind_info[next_state]->getTime()-World::getWorld()->getTime();
float dt = 1.0f/60.0f; float dt = 1.0f/60.0f;

View File

@ -108,6 +108,9 @@ private:
/** Time when this state was taken. */ /** Time when this state was taken. */
float m_time; float m_time;
/** Time step size. */
float m_time_step;
/** The 'left over' time from the physics. */ /** The 'left over' time from the physics. */
float m_local_physics_time; float m_local_physics_time;
@ -122,10 +125,10 @@ private:
/** The Rewinder instance for which this data is. */ /** The Rewinder instance for which this data is. */
Rewinder *m_rewinder; Rewinder *m_rewinder;
public: public:
RewindInfo(Rewinder *rewinder, float time, char *buffer, RewindInfo(Rewinder *rewinder, char *buffer,
bool is_event, bool is_confirmed); bool is_event, bool is_confirmed);
// -------------------------------------------------------------------- // --------------------------------------------------------------------
RewindInfo(float time); RewindInfo();
// -------------------------------------------------------------------- // --------------------------------------------------------------------
~RewindInfo() ~RewindInfo()
{ {
@ -138,6 +141,9 @@ private:
/** Returns the time at which this rewind state was saved. */ /** Returns the time at which this rewind state was saved. */
float getTime() const { return m_time; } float getTime() const { return m_time; }
// -------------------------------------------------------------------- // --------------------------------------------------------------------
/** Time step size. */
float getTimeStep() const { return m_time_step; }
// --------------------------------------------------------------------
bool isEvent() const { return m_type==RIT_EVENT; } bool isEvent() const { return m_type==RIT_EVENT; }
// -------------------------------------------------------------------- // --------------------------------------------------------------------
bool isTime() const { return m_type==RIT_TIME; } bool isTime() const { return m_type==RIT_TIME; }
@ -203,6 +209,15 @@ private:
/** Time at which the last state was saved. */ /** Time at which the last state was saved. */
float m_last_saved_state; float m_last_saved_state;
/** The current time to be used in all states/events. This is used to
* give all states and events during one frame the same time, even
* if e.g. states are saved before world time is increased, other
* events later. */
float m_current_time;
/** The current time step size. */
float m_time_step;
#define REWIND_SEARCH_STATS #define REWIND_SEARCH_STATS
#ifdef REWIND_SEARCH_STATS #ifdef REWIND_SEARCH_STATS
@ -223,6 +238,24 @@ public:
static RewindManager *create(); static RewindManager *create();
static void destroy(); static void destroy();
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Sets the time that is to be used for all further states or events,
* and the time step size. This is necessary so that states/events before
* and after World::m_time is increased have the same time stamp.
* \param t Time.
* \param dt Time step size.
*/
void setCurrentTime(float t, float dt)
{
m_current_time = t;
m_time_step = dt;
} // setCurrentTime
// ------------------------------------------------------------------------
/** Returns the current time. */
float getCurrentTime() const { return m_current_time; }
// ------------------------------------------------------------------------
float getCurrentTimeStep() const { return m_time_step; }
// ------------------------------------------------------------------------
/** En- or disables rewinding. */ /** En- or disables rewinding. */
static void setEnable(bool m) { m_enable_rewind_manager = m;} static void setEnable(bool m) { m_enable_rewind_manager = m;}
@ -242,7 +275,9 @@ public:
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void reset(); void reset();
void saveStates(float dt); void saveStates();
void rewindTo(float target_time);
void addEvent(Rewinder *rewinder, char *buffer);
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Adds a Rewinder to the list of all rewinders. /** Adds a Rewinder to the list of all rewinders.
* \return true If rewinding is enabled, false otherwise. * \return true If rewinding is enabled, false otherwise.
@ -254,9 +289,8 @@ public:
return true; return true;
} // addRewinder } // addRewinder
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void rewindTo(float target_time); /** Returns true if currently a rewind is happening. */
// ------------------------------------------------------------------------ bool isRewinding() const { return m_is_rewinding; }
void addEvent(Rewinder *rewinder, float time, char *buffer);
}; // RewindManager }; // RewindManager