Improve kart animation handling in network

This commit is contained in:
Benau
2018-08-04 16:29:49 +08:00
parent a892988b00
commit 79d1178626
12 changed files with 111 additions and 52 deletions

View File

@@ -504,15 +504,8 @@ void Powerup::hitBonusBox(const ItemState &item_state)
unsigned int n=1;
PowerupManager::PowerupType new_powerup;
// Check if rubber ball is the current power up held by the kart. If so,
// reset the bBallCollectTime to 0 before giving new powerup.
if(m_type == PowerupManager::POWERUP_RUBBERBALL)
powerup_manager->setBallCollectTicks(0);
World *world = World::getWorld();
// Determine a 'random' number based on time, index of the item,
// and position of the kart. The idea is that this process is
// randomly enough to get the right distribution of the powerups,

View File

@@ -143,9 +143,6 @@ private:
/** The icon for each powerup. */
Material* m_all_icons [POWERUP_MAX];
/** Last time the bouncing ball was collected */
int m_rubber_ball_collect_ticks;
/** The mesh for each model (if the powerup has a model), e.g. a switch
has none. */
irr::scene::IMesh *m_all_meshes[POWERUP_MAX];
@@ -174,13 +171,6 @@ public:
/** Returns the mesh for a certain powerup.
* \param type Mesh type for which the model is returned. */
irr::scene::IMesh *getMesh(int type) const {return m_all_meshes[type];}
// ------------------------------------------------------------------------
/** Returns the last time a rubber ball was collected. */
int getBallCollectTicks() const {return m_rubber_ball_collect_ticks;}
// ------------------------------------------------------------------------
/** Updates the last time at which a rubber ball was collected. */
void setBallCollectTicks(int ticks) {m_rubber_ball_collect_ticks=ticks;}
// ------------------------------------------------------------------------
}; // class PowerupManager
extern PowerupManager* powerup_manager;

View File

@@ -23,9 +23,12 @@
#include "karts/kart_model.hpp"
#include "karts/skidding.hpp"
#include "modes/world.hpp"
#include "network/network_config.hpp"
#include "network/rewind_manager.hpp"
#include "physics/physics.hpp"
#include <limits>
/** Constructor. Note that kart can be NULL in case that the animation is
* used for a basket ball in a cannon animation.
* \param kart Pointer to the kart that is animated, or NULL if the
@@ -37,7 +40,11 @@ AbstractKartAnimation::AbstractKartAnimation(AbstractKart *kart,
m_timer = 0;
m_kart = kart;
m_name = name;
m_end_transform = btTransform(btQuaternion(0.0f, 0.0f, 0.0f, 1.0f));
m_end_transform.setOrigin(Vec3(std::numeric_limits<float>::max()));
m_set_end_transform_by_network = NetworkConfig::get()->isNetworking() &&
NetworkConfig::get()->isClient() ? false : true;
m_created_ticks = World::getWorld()->getTicksSinceStart();
// Remove previous animation if there is one
#ifndef DEBUG
// Use this code in non-debug mode to avoid a memory leak (and messed
@@ -83,12 +90,15 @@ AbstractKartAnimation::~AbstractKartAnimation()
{
m_kart->getBody()->setAngularVelocity(btVector3(0,0,0));
Physics::getInstance()->addKart(m_kart);
if (RewindManager::get()->useLocalEvent())
if (RewindManager::get()->useLocalEvent() &&
m_set_end_transform_by_network)
{
AbstractKart* kart = m_kart;
Vec3 linear_velocity = kart->getBody()->getLinearVelocity();
Vec3 angular_velocity = kart->getBody()->getAngularVelocity();
btTransform transform = kart->getBody()->getWorldTransform();
btTransform transform = m_end_transform.getOrigin().x() ==
std::numeric_limits<float>::max() ?
kart->getBody()->getWorldTransform() : m_end_transform;
RewindManager::get()->addRewindInfoEventFunction(new
RewindInfoEventFunction(
World::getWorld()->getTicksSinceStart(),
@@ -125,4 +135,17 @@ void AbstractKartAnimation::update(float dt)
if(m_kart) m_kart->setKartAnimation(NULL);
delete this;
}
// Delete animation in client if after 1 second no end transform
// confirmation from network
if (NetworkConfig::get()->isNetworking() &&
NetworkConfig::get()->isClient() && !m_set_end_transform_by_network &&
World::getWorld()->getTicksSinceStart() > m_created_ticks + 120)
{
Log::warn("AbstractKartAnimation",
"No animation has been created on server, remove locally.");
m_timer = -1.0f;
if (m_kart)
m_kart->setKartAnimation(NULL);
delete this;
}
} // update

View File

@@ -19,6 +19,8 @@
#ifndef HEADER_ABSTRACT_KART_ANIMATION_HPP
#define HEADER_ABSTRACT_KART_ANIMATION_HPP
#include "LinearMath/btTransform.h"
#include "utils/no_copy.hpp"
#include "utils/vec3.hpp"
@@ -40,6 +42,9 @@ class AbstractKartAnimation: public NoCopy
private:
/** Name of this animation, used for debug prints only. */
std::string m_name;
int m_created_ticks;
protected:
/** A pointer to the kart which is animated by this class. */
AbstractKart *m_kart;
@@ -47,6 +52,10 @@ protected:
/** Timer for the explosion. */
float m_timer;
btTransform m_end_transform;
bool m_set_end_transform_by_network;
public:
AbstractKartAnimation(AbstractKart *kart,
const std::string &name);
@@ -59,7 +68,18 @@ public:
/** To easily allow printing the name of the animation being used atm.
* Used in AstractKart in case of an incorrect sequence of calls. */
virtual const std::string &getName() const { return m_name; }
// ------------------------------------------------------------------------
virtual bool useEarlyEndTransform() const { return true; }
// ------------------------------------------------------------------------
const btTransform& getEndTransform() const { return m_end_transform; }
// ------------------------------------------------------------------------
void setEndTransform(const btTransform& t)
{
if (!useEarlyEndTransform())
return;
m_set_end_transform_by_network = true;
m_end_transform = t;
}
}; // AbstractKartAnimation
#endif

View File

@@ -29,7 +29,7 @@
#include "LinearMath/btTransform.h"
/** The constructor for the cannon animation.
/** The constructor for the cannon animation.
* \param kart The kart to be animated. Can also be NULL if a basket ball
* etc is animated (e.g. cannon animation).
* \param ipo The IPO (blender interpolation curve) which the kart
@@ -48,6 +48,7 @@ CannonAnimation::CannonAnimation(AbstractKart *kart, Ipo *ipo,
float skid_rot)
: AbstractKartAnimation(kart, "CannonAnimation")
{
m_set_end_transform_by_network = true;
m_flyable = NULL;
init(ipo, start_left, start_right, end_left, end_right, skid_rot);
} // CannonAnimation
@@ -169,11 +170,11 @@ void CannonAnimation::init(Ipo *ipo, const Vec3 &start_left,
// Compute the original heading of the kart. At the end of the cannon,
// the kart should be parallel to the curve, but at the beginning it
// the kart should be parallel to the curve and facing forwards, but
// at the beginning it might not be. The initial rotation between the
// tangent of the curce and the kart is stored as a m_delta_heading,
// which will be applied to the curve orientation in update, but reduced
// over time till it becomes 0 at the end of the curve. The effect is that
// the kart should be parallel to the curve and facing forwards, but
// at the beginning it might not be. The initial rotation between the
// tangent of the curce and the kart is stored as a m_delta_heading,
// which will be applied to the curve orientation in update, but reduced
// over time till it becomes 0 at the end of the curve. The effect is that
// initially (t=0) the kart will keep its (non-orhtogonal) rotation,
// but smoothly this will adjusted until at the end the kart will be
// facing forwards again.

View File

@@ -80,6 +80,7 @@ public:
const Vec3 &end_left, const Vec3 &end_right);
virtual ~CannonAnimation();
virtual void update(float dt);
// ------------------------------------------------------------------------
virtual bool useEarlyEndTransform() const { return false; }
}; // CannonAnimation
#endif

View File

@@ -72,7 +72,8 @@ ExplosionAnimation::ExplosionAnimation(AbstractKart *kart,
const Vec3 &explosion_position,
bool direct_hit)
: AbstractKartAnimation(kart, "ExplosionAnimation")
{
{
m_end_transform = m_kart->getTrans();
m_xyz = m_kart->getXYZ();
m_orig_xyz = m_xyz;
m_normal = m_kart->getNormal();
@@ -109,8 +110,7 @@ ExplosionAnimation::ExplosionAnimation(AbstractKart *kart,
m_kart->showStarEffect(t);
m_kart->getAttachment()->clear();
}; // ExplosionAnimation
} // ExplosionAnimation
//-----------------------------------------------------------------------------
ExplosionAnimation::~ExplosionAnimation()

View File

@@ -464,7 +464,11 @@ public:
// ------------------------------------------------------------------------
/** Makes a kart invulnerable for a certain amount of time. */
virtual void setInvulnerableTicks(int ticks) OVERRIDE
{
{
// The rest 2 bits are saving fire clicked and animation status for
// rewind
if (ticks > 16383)
ticks = 16383;
m_invulnerable_ticks = ticks;
} // setInvulnerableTicks
// ------------------------------------------------------------------------

View File

@@ -21,6 +21,7 @@
#include "items/attachment.hpp"
#include "items/powerup.hpp"
#include "karts/abstract_kart.hpp"
#include "karts/abstract_kart_animation.hpp"
#include "karts/controller/player_controller.hpp"
#include "karts/kart_properties.hpp"
#include "karts/max_speed.hpp"
@@ -154,10 +155,20 @@ BareNetworkString* KartRewinder::saveState(std::vector<std::string>* ru)
buffer->addUInt16(m_bubblegum_ticks);
buffer->addUInt16(m_view_blocked_by_plunger);
// m_invulnerable_ticks will not be negative
AbstractKartAnimation* ka = getKartAnimation();
bool has_animation = ka != NULL && ka->useEarlyEndTransform();
uint16_t fire_and_invulnerable = (m_fire_clicked ? 1 << 15 : 0) |
m_invulnerable_ticks;
(has_animation ? 1 << 14 : 0) | m_invulnerable_ticks;
buffer->addUInt16(fire_and_invulnerable);
// 7) Kart animation status (tells the end transformation)
if (has_animation)
{
const btTransform& trans = ka->getEndTransform();
buffer->add(trans.getOrigin());
btQuaternion quat = trans.getRotation();
buffer->add(quat);
}
return buffer;
} // saveState
@@ -242,7 +253,20 @@ void KartRewinder::restoreState(BareNetworkString *buffer, int count)
m_view_blocked_by_plunger = buffer->getUInt16();
uint16_t fire_and_invulnerable = buffer->getUInt16();
m_fire_clicked = (fire_and_invulnerable >> 15) == 1;
m_invulnerable_ticks = fire_and_invulnerable & ~(1 << 15);
bool has_animation = (fire_and_invulnerable >> 14) == 1;
m_invulnerable_ticks = fire_and_invulnerable & ~(1 << 14);
// 7) Kart animation status (tells the end transformation)
// -----------
if (has_animation)
{
btTransform trans;
trans.setOrigin(buffer->getVec3());
trans.setRotation(buffer->getQuat());
AbstractKartAnimation* ka = getKartAnimation();
if (ka)
ka->setEndTransform(trans);
}
} // restoreState
// ----------------------------------------------------------------------------

View File

@@ -45,6 +45,14 @@
RescueAnimation::RescueAnimation(AbstractKart *kart, bool is_auto_rescue)
: AbstractKartAnimation(kart, "RescueAnimation")
{
btTransform prev_trans = kart->getTrans();
// Get the required final physicial transform for network, then reset back
// to the original transform
World::getWorld()->moveKartAfterRescue(kart);
m_end_transform = kart->getTrans();
kart->setTrans(prev_trans);
m_referee = new Referee(*m_kart);
m_kart->getNode()->addChild(m_referee->getSceneNode());
m_timer = m_kart->getKartProperties()->getRescueDuration();
@@ -56,7 +64,7 @@ RescueAnimation::RescueAnimation(AbstractKart *kart, bool is_auto_rescue)
// Determine maximum rescue height with up-raycast
float max_height = m_kart->getKartProperties()->getRescueHeight();
float hit_dest = maximumHeight();
max_height = std::min(hit_dest, max_height);
m_velocity = max_height / m_timer;
@@ -80,7 +88,7 @@ RescueAnimation::RescueAnimation(AbstractKart *kart, bool is_auto_rescue)
{
m_des_rotation = m_orig_rotation;
}
// Add a hit unless it was auto-rescue
if (race_manager->getMinorMode()==RaceManager::MINOR_MODE_3_STRIKES &&
!is_auto_rescue)
@@ -91,8 +99,7 @@ RescueAnimation::RescueAnimation(AbstractKart *kart, bool is_auto_rescue)
world->increaseRescueCount();
}
}; // RescueAnimation
} // RescueAnimation
//-----------------------------------------------------------------------------
/** This object is automatically destroyed when the timer expires.
@@ -106,7 +113,9 @@ RescueAnimation::~RescueAnimation()
m_referee = NULL;
} // ~RescueAnimation
// Determine maximum rescue height with up-raycast
//-----------------------------------------------------------------------------
/** Determine maximum rescue height with up-raycast
*/
float RescueAnimation::maximumHeight()
{
float hit_dest = 9999999.9f;
@@ -125,24 +134,21 @@ float RescueAnimation::maximumHeight()
}
}
return hit_dest;
}
// ----------------------------------------------------------------------------
} // maximumHeight
// ----------------------------------------------------------------------------
/** Updates the kart animation.
* \param dt Time step size.
* \return True if the explosion is still shown, false if it has finished.
*/
void RescueAnimation::update(float dt)
{
if (m_timer <= (m_kart->getKartProperties()->getRescueDuration() * rescue_moment))
{
if (kart_on_track == false)
if (m_kart_on_track == false)
{
kart_on_track = true;
World::getWorld()->moveKartAfterRescue(m_kart);
m_kart_on_track = true;
m_kart->setTrans(m_end_transform);
for (unsigned int i = 0; i < Camera::getNumCameras(); i++)
{
CameraNormal* camera = dynamic_cast<CameraNormal*>(Camera::getCamera(i));

View File

@@ -50,8 +50,8 @@ protected:
/*0.75 means that for 3 quaters of the animation it'll be on track*/
const float rescue_moment = 0.6F;
/* Has the kart been moved onto the track */
bool kart_on_track = false;
bool m_kart_on_track = false;
/** The referee during a rescue operation. */
Referee *m_referee;

View File

@@ -312,9 +312,6 @@ void World::reset()
// Reset all data structures that depend on number of karts.
irr_driver->reset();
//Reset the Rubber Ball Collect Time to some negative value.
powerup_manager->setBallCollectTicks(-100);
} // reset
//-----------------------------------------------------------------------------