Make check cannon rewind-friendly without using previous position

This commit is contained in:
Benau 2019-03-17 12:35:42 +08:00
parent 5b4ae2a59f
commit 2aede6fa25
3 changed files with 38 additions and 61 deletions

View File

@ -124,71 +124,48 @@ void CheckCannon::changeDebugColor(bool is_active)
#endif
} // changeDebugColor
// ----------------------------------------------------------------------------
/** Adds a flyable to be tested for crossing a cannon checkline.
* \param flyable The flyable to be tested.
*/
void CheckCannon::addFlyable(Flyable* flyable)
{
m_all_flyables_previous_position[flyable] = flyable->getXYZ();
} // addFlyable
// ----------------------------------------------------------------------------
/** Overriden to also check all flyables registered with the cannon.
*/
void CheckCannon::update(float dt)
{
CheckLine::update(dt);
for (auto& f : m_all_flyables_previous_position)
World* world = World::getWorld();
for (unsigned int i = 0; i < world->getNumKarts(); i++)
{
AbstractKart* kart = world->getKart(i);
if (kart->getKartAnimation() || kart->isGhostKart() ||
kart->isEliminated() || !m_is_active[i])
continue;
const Vec3& xyz = world->getKart(i)->getFrontXYZ();
Vec3 prev_xyz = xyz - kart->getVelocity() * dt;
if (isTriggered(prev_xyz, xyz, /*kart index - ignore*/ -1))
{
// The constructor AbstractKartAnimation resets the skidding to 0.
// So in order to smooth rotate the kart, we need to keep the
// current visual rotation and pass it to the CannonAnimation.
float skid_rot = kart->getSkidding()->getVisualSkidRotation();
new CannonAnimation(kart, this, skid_rot);
}
} // for i < getNumKarts
for (Flyable* flyable : m_all_flyables)
{
Flyable* flyable = f.first;
if (!flyable->hasServerState() || flyable->hasAnimation())
continue;
const Vec3& previous_position = f.second;
const Vec3 current_position = flyable->getXYZ();
Vec3 previous_position = current_position - flyable->getVelocity() * dt;
setIgnoreHeight(true);
bool triggered = isTriggered(previous_position, current_position,
/*kart index - ignore*/ -1);
setIgnoreHeight(false);
f.second = current_position;
if (!triggered) continue;
if (!triggered)
continue;
// Cross the checkline - add the cannon animation
CannonAnimation* animation = new CannonAnimation(flyable,
this);
CannonAnimation* animation = new CannonAnimation(flyable, this);
flyable->setAnimation(animation);
} // for i in all flyables
} // update
// ----------------------------------------------------------------------------
/** Called when the check line is triggered. This function creates a cannon
* animation object and attaches it to the kart.
* \param kart_index The index of the kart that triggered the check line.
*/
void CheckCannon::trigger(unsigned int kart_index)
{
AbstractKart *kart = World::getWorld()->getKart(kart_index);
if (kart->getKartAnimation() || kart->isGhostKart())
return;
// The constructor AbstractKartAnimation resets the skidding to 0. So in
// order to smooth rotate the kart, we need to keep the current visual
// rotation and pass it to the CannonAnimation.
float skid_rot = kart->getSkidding()->getVisualSkidRotation();
new CannonAnimation(kart, this, skid_rot);
} // trigger
// ----------------------------------------------------------------------------
void CheckCannon::resetAfterRewind(unsigned int kart_index)
{
CheckLine::resetAfterRewind(kart_index);
for (auto& f : m_all_flyables_previous_position)
{
Flyable* flyable = f.first;
if (!flyable->hasServerState() || flyable->hasAnimation())
continue;
f.second = flyable->getXYZ();
}
} // resetAfterRewind

View File

@ -23,7 +23,7 @@
#include "tracks/check_line.hpp"
#include "utils/cpp2011.hpp"
#include <map>
#include <set>
class CheckManager;
class Flyable;
@ -61,13 +61,13 @@ private:
std::shared_ptr<SP::SPDynamicDrawCall> m_debug_target_dy_dc;
#endif
std::map<Flyable*, Vec3> m_all_flyables_previous_position;
std::set<Flyable*> m_all_flyables;
public:
CheckCannon(const XMLNode &node, unsigned int index);
// ------------------------------------------------------------------------
virtual ~CheckCannon();
// ------------------------------------------------------------------------
virtual void trigger(unsigned int kart_index) OVERRIDE;
virtual void trigger(unsigned int kart_index) OVERRIDE {}
// ------------------------------------------------------------------------
virtual void changeDebugColor(bool is_active) OVERRIDE;
// ------------------------------------------------------------------------
@ -75,15 +75,15 @@ public:
// ------------------------------------------------------------------------
virtual bool triggeringCheckline() const OVERRIDE { return false; }
// ------------------------------------------------------------------------
virtual void resetAfterRewind(unsigned int kart_index) OVERRIDE;
// ------------------------------------------------------------------------
void addFlyable(Flyable* flyable);
/** Adds a flyable to be tested for crossing a cannon checkline.
* \param flyable The flyable to be tested.
*/
void addFlyable(Flyable* flyable) { m_all_flyables.insert(flyable); }
// ------------------------------------------------------------------------
/** Removes a flyable from the tests if it crosses a checkline. Used when
* the flyable is removed (e.g. explodes).
*/
void removeFlyable(Flyable* flyable)
{ m_all_flyables_previous_position.erase(flyable); }
void removeFlyable(Flyable* flyable) { m_all_flyables.erase(flyable); }
// ------------------------------------------------------------------------
const Vec3& getTargetLeft() const { return m_target_left; }
// ------------------------------------------------------------------------

View File

@ -191,17 +191,17 @@ bool CheckLine::isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
result = m_ignore_height ||
(new_pos.getY()-m_min_height<m_over_min_height &&
new_pos.getY()-m_min_height>-m_under_min_height );
if(UserConfigParams::m_check_debug && !result)
if (UserConfigParams::m_check_debug && !result)
{
if(World::getWorld()->getNumKarts()>0)
if (kart_index >= 0)
Log::info("CheckLine", "Kart %s crosses line, but wrong height "
"(%f vs %f).",
World::getWorld()->getKart(kart_index)->getIdent().c_str(),
new_pos.getY(), m_min_height);
else
Log::info("CheckLine", "Kart %d crosses line, but wrong height "
else if (!result)
Log::info("CheckLine", "Object crosses line, but wrong height "
"(%f vs %f).",
kart_index, new_pos.getY(), m_min_height);
new_pos.getY(), m_min_height);
}
}
else