Fix rewind issue of rubber ball

This commit is contained in:
Benau
2018-08-06 14:37:55 +08:00
parent f5a308f94b
commit 93aeeda12b
5 changed files with 62 additions and 37 deletions

View File

@@ -638,6 +638,7 @@ void Flyable::restoreState(BareNetworkString *buffer, int count)
m_body->setAngularVelocity(av);
m_body->setInterpolationLinearVelocity(lv);
m_body->setInterpolationAngularVelocity(av);
setTrans(t);
}
uint16_t hit_and_ticks = buffer->getUInt16();
m_has_hit_something = (hit_and_ticks >> 15) == 1;

View File

@@ -106,6 +106,7 @@ void RubberBall::additionalPhysicsProperties()
// FIXME: what does the rubber ball do in case of battle mode??
if(!world) return;
m_restoring_state = true;
computeTarget();
// initialises the current graph node
@@ -197,6 +198,14 @@ void RubberBall::computeTarget()
{
LinearWorld *world = dynamic_cast<LinearWorld*>(World::getWorld());
if (m_restoring_state)
{
// Update kart position from rewind data 1st time
world->updateTrackSectors();
world->updateRacePosition();
m_restoring_state = false;
}
for(unsigned int p = race_manager->getFinishedKarts()+1;
p < world->getNumKarts()+1; p++)
{
@@ -374,6 +383,11 @@ bool RubberBall::updateAndDelete(int ticks)
return Flyable::updateAndDelete(ticks);
}
// Update normal from rewind first
const Vec3& normal =
DriveGraph::get()->getNode(getCurrentGraphNode())->getNormal();
TerrainInfo::update(getXYZ(), -normal);
// Update the target in case that the first kart was overtaken (or has
// finished the race).
computeTarget();
@@ -397,7 +411,7 @@ bool RubberBall::updateAndDelete(int ticks)
bool close_to_ground = 2.0*m_previous_height < m_current_max_height;
float vertical_offset = close_to_ground ? 4.0f : 2.0f;
// Update height of terrain (which isn't done as part of
// Flyable::update for rubber balls.
TerrainInfo::update(next_xyz + getNormal()*vertical_offset, -getNormal());
@@ -482,7 +496,7 @@ void RubberBall::moveTowardsTarget(Vec3 *next_xyz, int ticks)
}
// If ball is close to the target, then explode
if (diff.length() < m_target->getKartLength())
if (diff.length() < m_target->getKartLength())
hit((AbstractKart*)m_target);
assert(!std::isnan((*next_xyz)[0]));
@@ -691,6 +705,10 @@ void RubberBall::updateDistanceToTarget()
{
m_fast_ping = true;
}
else
{
m_fast_ping = false;
}
if(m_distance_to_target < m_st_target_distance &&
height_diff < m_st_max_height_difference)
{
@@ -785,13 +803,10 @@ BareNetworkString* RubberBall::saveState(std::vector<std::string>* ru)
buffer->addFloat(m_t);
buffer->addFloat(m_t_increase);
buffer->addFloat(m_interval);
buffer->addUInt8(m_fast_ping ? 1 : 0);
buffer->addFloat(m_distance_to_target);
buffer->addFloat(m_height_timer);
buffer->addUInt32(m_delete_ticks);
buffer->addFloat(m_current_max_height);
buffer->addUInt8(m_aiming_at_target ? 1 : 0);
buffer->addUInt32(m_tunnel_count);
buffer->addUInt8(m_tunnel_count | (m_aiming_at_target ? (1 << 7) : 0));
TrackSector::saveState(buffer);
return buffer;
} // saveState
@@ -800,6 +815,7 @@ BareNetworkString* RubberBall::saveState(std::vector<std::string>* ru)
void RubberBall::restoreState(BareNetworkString *buffer, int count)
{
Flyable::restoreState(buffer, count);
m_restoring_state = true;
m_last_aimed_graph_node = buffer->getUInt32();
m_control_points[0] = buffer->getVec3();
m_control_points[1] = buffer->getVec3();
@@ -812,12 +828,11 @@ void RubberBall::restoreState(BareNetworkString *buffer, int count)
m_t = buffer->getFloat();
m_t_increase = buffer->getFloat();
m_interval = buffer->getFloat();
m_fast_ping = buffer->getUInt8() == 1;
m_distance_to_target = buffer->getFloat();
m_height_timer = buffer->getFloat();
m_delete_ticks = buffer->getUInt32();
m_current_max_height = buffer->getFloat();
m_aiming_at_target = buffer->getUInt8() == 1;
m_tunnel_count = buffer->getUInt32();
uint8_t tunnel_and_aiming = buffer->getUInt8();
m_tunnel_count = tunnel_and_aiming & 127;
m_aiming_at_target = ((tunnel_and_aiming >> 7) & 1) == 1;
TrackSector::rewindTo(buffer);
} // restoreState

View File

@@ -177,7 +177,7 @@ private:
/** This variable counts how often a ball tunneled (in consecutive
* frames). If a ball tunnels a certain number of times, it is
* considered stuck and will be removed. */
unsigned int m_tunnel_count;
uint8_t m_tunnel_count;
/** A 'ping' sound effect to be played when the ball hits the ground. */
SFXBase *m_ping_sfx;
@@ -185,6 +185,8 @@ private:
/* Used by undo and redo the firing when rewind */
Vec3 m_owner_init_pos, m_init_pos;
bool m_restoring_state;
void computeTarget();
void updateDistanceToTarget();
unsigned int getSuccessorToHitTarget(unsigned int node_index,

View File

@@ -169,34 +169,10 @@ void LinearWorld::update(int ticks)
m_finish_timeout = std::numeric_limits<float>::max();
}
}
const unsigned int kart_amount = getNumKarts();
// Do stuff specific to this subtype of race.
// ------------------------------------------
for(unsigned int n=0; n<kart_amount; n++)
{
KartInfo& kart_info = m_kart_info[n];
AbstractKart* kart = m_karts[n].get();
// Nothing to do for karts that are currently being
// rescued or eliminated
if(kart->getKartAnimation()) continue;
// If the kart is off road, and 'flying' over a reset plane
// don't adjust the distance of the kart, to avoid a jump
// in the position of the kart (e.g. while falling the kart
// might get too close to another part of the track, shortly
// jump to position one, then on reset fall back to last)
if ((!getTrackSector(n)->isOnRoad() &&
(!kart->getMaterial() ||
kart->getMaterial()->isDriveReset())) &&
!kart->isGhostKart())
continue;
getTrackSector(n)->update(kart->getFrontXYZ());
kart_info.m_overall_distance = kart_info.m_finished_laps
* Track::getCurrentTrack()->getTrackLength()
+ getDistanceDownTrackForKart(kart->getWorldKartId(), true);
} // for n
updateTrackSectors();
// 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
@@ -209,6 +185,7 @@ void LinearWorld::update(int ticks)
WorldWithRank::updateTrack(ticks);
updateRacePosition();
const unsigned int kart_amount = getNumKarts();
for (unsigned int i=0; i<kart_amount; i++)
{
// ---------- update rank ------
@@ -251,6 +228,35 @@ void LinearWorld::update(int ticks)
#endif
} // update
//-----------------------------------------------------------------------------
void LinearWorld::updateTrackSectors()
{
const unsigned int kart_amount = getNumKarts();
for(unsigned int n=0; n<kart_amount; n++)
{
KartInfo& kart_info = m_kart_info[n];
AbstractKart* kart = m_karts[n].get();
// Nothing to do for karts that are currently being
// rescued or eliminated
if(kart->getKartAnimation()) continue;
// If the kart is off road, and 'flying' over a reset plane
// don't adjust the distance of the kart, to avoid a jump
// in the position of the kart (e.g. while falling the kart
// might get too close to another part of the track, shortly
// jump to position one, then on reset fall back to last)
if ((!getTrackSector(n)->isOnRoad() &&
(!kart->getMaterial() ||
kart->getMaterial()->isDriveReset())) &&
!kart->isGhostKart())
continue;
getTrackSector(n)->update(kart->getFrontXYZ());
kart_info.m_overall_distance = kart_info.m_finished_laps
* Track::getCurrentTrack()->getTrackLength()
+ getDistanceDownTrackForKart(kart->getWorldKartId(), true);
} // for n
} // updateTrackSectors
//-----------------------------------------------------------------------------
/** This updates all only graphical elements.It is only called once per
* rendered frame, not once per time step.

View File

@@ -124,7 +124,6 @@ protected:
AlignedArray<KartInfo> m_kart_info;
virtual void checkForWrongDirection(unsigned int i, float dt);
void updateRacePosition();
virtual float estimateFinishTimeForKart(AbstractKart* kart) OVERRIDE;
public:
@@ -139,6 +138,8 @@ public:
virtual void updateGraphics(float dt) OVERRIDE;
float getDistanceDownTrackForKart(const int kart_id,
bool account_for_checklines) const;
void updateTrackSectors();
void updateRacePosition();
float getDistanceToCenterForKart(const int kart_id) const;
float getEstimatedFinishTime(const int kart_id) const;
int getLapForKart(const int kart_id) const;