First fix for the basket-ball in cannon - make the ball follow
the cannon.
This commit is contained in:
parent
03f4b76a32
commit
1b75ed9b4c
@ -67,13 +67,14 @@ Flyable::Flyable(AbstractKart *kart, PowerupManager::PowerupType type,
|
|||||||
m_type = type;
|
m_type = type;
|
||||||
m_has_hit_something = false;
|
m_has_hit_something = false;
|
||||||
m_shape = NULL;
|
m_shape = NULL;
|
||||||
|
m_animation = NULL;
|
||||||
m_mass = mass;
|
m_mass = mass;
|
||||||
m_adjust_up_velocity = true;
|
m_adjust_up_velocity = true;
|
||||||
m_time_since_thrown = 0;
|
m_time_since_thrown = 0;
|
||||||
m_position_offset = Vec3(0,0,0);
|
m_position_offset = Vec3(0,0,0);
|
||||||
m_owner_has_temporary_immunity = true;
|
m_owner_has_temporary_immunity = true;
|
||||||
m_do_terrain_info = true;
|
m_do_terrain_info = true;
|
||||||
m_max_lifespan = -1;
|
m_max_lifespan = -1;
|
||||||
|
|
||||||
// Add the graphical model
|
// Add the graphical model
|
||||||
#ifndef SERVER_ONLY
|
#ifndef SERVER_ONLY
|
||||||
@ -353,6 +354,24 @@ void Flyable::getLinearKartItemIntersection (const Vec3 &origin,
|
|||||||
+ ( target_y_speed);
|
+ ( target_y_speed);
|
||||||
} // getLinearKartItemIntersection
|
} // getLinearKartItemIntersection
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void Flyable::setAnimation(AbstractKartAnimation *animation)
|
||||||
|
{
|
||||||
|
if (animation)
|
||||||
|
{
|
||||||
|
assert(m_animation == NULL);
|
||||||
|
Physics::getInstance()->removeBody(m_body);
|
||||||
|
}
|
||||||
|
else // animation = NULL
|
||||||
|
{
|
||||||
|
assert(m_animation != NULL);
|
||||||
|
m_body->setWorldTransform(getTrans());
|
||||||
|
Physics::getInstance()->addBody(m_body);
|
||||||
|
}
|
||||||
|
m_animation = animation;
|
||||||
|
} // addAnimation
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
/** Updates this flyable. It calls Moveable::update. If this function returns
|
/** Updates this flyable. It calls Moveable::update. If this function returns
|
||||||
* true, the flyable will be deleted by the projectile manager.
|
* true, the flyable will be deleted by the projectile manager.
|
||||||
@ -361,6 +380,13 @@ void Flyable::getLinearKartItemIntersection (const Vec3 &origin,
|
|||||||
*/
|
*/
|
||||||
bool Flyable::updateAndDelete(float dt)
|
bool Flyable::updateAndDelete(float dt)
|
||||||
{
|
{
|
||||||
|
if (hasAnimation())
|
||||||
|
{
|
||||||
|
m_animation->update(dt);
|
||||||
|
Moveable::update(dt);
|
||||||
|
return false;
|
||||||
|
} // if animation
|
||||||
|
|
||||||
m_time_since_thrown += dt;
|
m_time_since_thrown += dt;
|
||||||
if(m_max_lifespan > -1 && m_time_since_thrown > m_max_lifespan)
|
if(m_max_lifespan > -1 && m_time_since_thrown > m_max_lifespan)
|
||||||
hit(NULL);
|
hit(NULL);
|
||||||
|
@ -34,6 +34,7 @@ using namespace irr;
|
|||||||
#include "tracks/terrain_info.hpp"
|
#include "tracks/terrain_info.hpp"
|
||||||
|
|
||||||
class AbstractKart;
|
class AbstractKart;
|
||||||
|
class AbstractKartAnimation;
|
||||||
class HitEffect;
|
class HitEffect;
|
||||||
class PhysicalObject;
|
class PhysicalObject;
|
||||||
class XMLNode;
|
class XMLNode;
|
||||||
@ -64,6 +65,11 @@ private:
|
|||||||
* terrain yourself (e.g. order of operations is important)
|
* terrain yourself (e.g. order of operations is important)
|
||||||
* set this to false with a call do setDoTerrainInfo(). */
|
* set this to false with a call do setDoTerrainInfo(). */
|
||||||
bool m_do_terrain_info;
|
bool m_do_terrain_info;
|
||||||
|
|
||||||
|
/** If the flyable is in a cannon, this is the pointer to the cannon
|
||||||
|
* animation. NULL otherwise. */
|
||||||
|
AbstractKartAnimation *m_animation;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/** Kart which shot this flyable. */
|
/** Kart which shot this flyable. */
|
||||||
AbstractKart* m_owner;
|
AbstractKart* m_owner;
|
||||||
@ -162,11 +168,16 @@ public:
|
|||||||
static void init (const XMLNode &node, scene::IMesh *model,
|
static void init (const XMLNode &node, scene::IMesh *model,
|
||||||
PowerupManager::PowerupType type);
|
PowerupManager::PowerupType type);
|
||||||
virtual bool updateAndDelete(float);
|
virtual bool updateAndDelete(float);
|
||||||
|
virtual void setAnimation(AbstractKartAnimation *animation);
|
||||||
virtual HitEffect* getHitEffect() const;
|
virtual HitEffect* getHitEffect() const;
|
||||||
bool isOwnerImmunity(const AbstractKart *kart_hit) const;
|
bool isOwnerImmunity(const AbstractKart *kart_hit) const;
|
||||||
virtual bool hit(AbstractKart* kart, PhysicalObject* obj=NULL);
|
virtual bool hit(AbstractKart* kart, PhysicalObject* obj=NULL);
|
||||||
void explode(AbstractKart* kart, PhysicalObject* obj=NULL,
|
void explode(AbstractKart* kart, PhysicalObject* obj=NULL,
|
||||||
bool secondary_hits=true);
|
bool secondary_hits=true);
|
||||||
|
unsigned int getOwnerId();
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
/** Returns if this flyable has an animation playing (e.g. cannon). */
|
||||||
|
bool hasAnimation() const { return m_animation != NULL; }
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
/** If true the up velocity of the flyable will be adjust so that the
|
/** If true the up velocity of the flyable will be adjust so that the
|
||||||
* flyable stays at a height close to the average height.
|
* flyable stays at a height close to the average height.
|
||||||
@ -194,15 +205,16 @@ public:
|
|||||||
void reset () { Moveable::reset(); }
|
void reset () { Moveable::reset(); }
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
/** Returns the type of flyable. */
|
/** Returns the type of flyable. */
|
||||||
PowerupManager::PowerupType
|
PowerupManager::PowerupType getType() const {return m_type;}
|
||||||
getType() const {return m_type;}
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
/** Sets wether Flyable should update TerrainInfo as part of its update
|
/** Sets wether Flyable should update TerrainInfo as part of its update
|
||||||
* call, or if the inheriting object will update TerrainInfo itself
|
* call, or if the inheriting object will update TerrainInfo itself
|
||||||
* (or perhaps not at all if it is not needed). */
|
* (or perhaps not at all if it is not needed). */
|
||||||
void setDoTerrainInfo(bool d) { m_do_terrain_info = d; }
|
void setDoTerrainInfo(bool d) { m_do_terrain_info = d; }
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
unsigned int getOwnerId();
|
/** Returns the size (extend) of the mesh. */
|
||||||
|
const Vec3 &getExtend() const { return m_extend; }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
}; // Flyable
|
}; // Flyable
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
#include "modes/linear_world.hpp"
|
#include "modes/linear_world.hpp"
|
||||||
#include "physics/btKart.hpp"
|
#include "physics/btKart.hpp"
|
||||||
#include "physics/triangle_mesh.hpp"
|
#include "physics/triangle_mesh.hpp"
|
||||||
|
#include "tracks/check_manager.hpp"
|
||||||
#include "tracks/drive_graph.hpp"
|
#include "tracks/drive_graph.hpp"
|
||||||
#include "tracks/drive_node.hpp"
|
#include "tracks/drive_node.hpp"
|
||||||
#include "tracks/track.hpp"
|
#include "tracks/track.hpp"
|
||||||
@ -103,7 +104,7 @@ RubberBall::RubberBall(AbstractKart *kart)
|
|||||||
DriveGraph::get()->getNode(getCurrentGraphNode())->getNormal();
|
DriveGraph::get()->getNode(getCurrentGraphNode())->getNormal();
|
||||||
TerrainInfo::update(getXYZ(), -normal);
|
TerrainInfo::update(getXYZ(), -normal);
|
||||||
initializeControlPoints(m_owner->getXYZ());
|
initializeControlPoints(m_owner->getXYZ());
|
||||||
|
CheckManager::get()->addFlyableToCannons(this);
|
||||||
} // RubberBall
|
} // RubberBall
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@ -114,6 +115,7 @@ RubberBall::~RubberBall()
|
|||||||
if(m_ping_sfx->getStatus()==SFXBase::SFX_PLAYING)
|
if(m_ping_sfx->getStatus()==SFXBase::SFX_PLAYING)
|
||||||
m_ping_sfx->stop();
|
m_ping_sfx->stop();
|
||||||
m_ping_sfx->deleteSFX();
|
m_ping_sfx->deleteSFX();
|
||||||
|
CheckManager::get()->removeFlyableFromCannons(this);
|
||||||
} // ~RubberBall
|
} // ~RubberBall
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@ -145,6 +147,14 @@ void RubberBall::initializeControlPoints(const Vec3 &xyz)
|
|||||||
m_t_increase = m_speed/m_length_cp_1_2;
|
m_t_increase = m_speed/m_length_cp_1_2;
|
||||||
} // initializeControlPoints
|
} // initializeControlPoints
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
void RubberBall::setAnimation(AbstractKartAnimation *animation)
|
||||||
|
{
|
||||||
|
if (!animation)
|
||||||
|
initializeControlPoints(getXYZ());
|
||||||
|
Flyable::setAnimation(animation);
|
||||||
|
} // setAnimation
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
/** Determines the first kart that is still in the race.
|
/** Determines the first kart that is still in the race.
|
||||||
*/
|
*/
|
||||||
@ -310,6 +320,7 @@ bool RubberBall::updateAndDelete(float dt)
|
|||||||
// FIXME: what does the rubber ball do in case of battle mode??
|
// FIXME: what does the rubber ball do in case of battle mode??
|
||||||
if(!world) return true;
|
if(!world) return true;
|
||||||
|
|
||||||
|
|
||||||
if(m_delete_timer>0)
|
if(m_delete_timer>0)
|
||||||
{
|
{
|
||||||
m_delete_timer -= dt;
|
m_delete_timer -= dt;
|
||||||
@ -323,6 +334,14 @@ bool RubberBall::updateAndDelete(float dt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hasAnimation())
|
||||||
|
{
|
||||||
|
// Flyable will call update() of the animation to
|
||||||
|
// update the ball's position.
|
||||||
|
m_previous_xyz = getXYZ();
|
||||||
|
return Flyable::updateAndDelete(dt);
|
||||||
|
}
|
||||||
|
|
||||||
// Update the target in case that the first kart was overtaken (or has
|
// Update the target in case that the first kart was overtaken (or has
|
||||||
// finished the race).
|
// finished the race).
|
||||||
computeTarget();
|
computeTarget();
|
||||||
|
@ -204,6 +204,7 @@ public:
|
|||||||
static void init(const XMLNode &node, scene::IMesh *rubberball);
|
static void init(const XMLNode &node, scene::IMesh *rubberball);
|
||||||
virtual bool updateAndDelete(float dt);
|
virtual bool updateAndDelete(float dt);
|
||||||
virtual bool hit(AbstractKart* kart, PhysicalObject* obj=NULL);
|
virtual bool hit(AbstractKart* kart, PhysicalObject* obj=NULL);
|
||||||
|
virtual void setAnimation(AbstractKartAnimation *animation);
|
||||||
static float getTimeBetweenRubberBalls() {return m_time_between_balls;}
|
static float getTimeBetweenRubberBalls() {return m_time_between_balls;}
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
/** This object does not create an explosion, all affects on
|
/** This object does not create an explosion, all affects on
|
||||||
|
@ -24,6 +24,11 @@
|
|||||||
#include "karts/skidding.hpp"
|
#include "karts/skidding.hpp"
|
||||||
#include "physics/physics.hpp"
|
#include "physics/physics.hpp"
|
||||||
|
|
||||||
|
/** 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
|
||||||
|
* the animation is meant for a basket ball etc.
|
||||||
|
*/
|
||||||
AbstractKartAnimation::AbstractKartAnimation(AbstractKart *kart,
|
AbstractKartAnimation::AbstractKartAnimation(AbstractKart *kart,
|
||||||
const std::string &name)
|
const std::string &name)
|
||||||
{
|
{
|
||||||
@ -37,7 +42,7 @@ AbstractKartAnimation::AbstractKartAnimation(AbstractKart *kart,
|
|||||||
// up animations) if this should happen. In debug mode this condition
|
// up animations) if this should happen. In debug mode this condition
|
||||||
// is caught by setKartAnimation(), and useful error messages are
|
// is caught by setKartAnimation(), and useful error messages are
|
||||||
// printed
|
// printed
|
||||||
if (kart->getKartAnimation())
|
if (kart && kart->getKartAnimation())
|
||||||
{
|
{
|
||||||
AbstractKartAnimation* ka = kart->getKartAnimation();
|
AbstractKartAnimation* ka = kart->getKartAnimation();
|
||||||
kart->setKartAnimation(NULL);
|
kart->setKartAnimation(NULL);
|
||||||
@ -46,21 +51,23 @@ AbstractKartAnimation::AbstractKartAnimation(AbstractKart *kart,
|
|||||||
#endif
|
#endif
|
||||||
// Register this animation with the kart (which will free it
|
// Register this animation with the kart (which will free it
|
||||||
// later).
|
// later).
|
||||||
kart->setKartAnimation(this);
|
if (kart)
|
||||||
Physics::getInstance()->removeKart(m_kart);
|
|
||||||
kart->getSkidding()->reset();
|
|
||||||
kart->getSlipstream()->reset();
|
|
||||||
if(kart->isSquashed())
|
|
||||||
{
|
{
|
||||||
// A time of 0 reset the squashing
|
kart->setKartAnimation(this);
|
||||||
kart->setSquash(0.0f, 0.0f);
|
Physics::getInstance()->removeKart(m_kart);
|
||||||
|
kart->getSkidding()->reset();
|
||||||
|
kart->getSlipstream()->reset();
|
||||||
|
if (kart->isSquashed())
|
||||||
|
{
|
||||||
|
// A time of 0 reset the squashing
|
||||||
|
kart->setSquash(0.0f, 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset the wheels (and any other animation played for that kart)
|
||||||
|
// This avoid the effect that some wheels might be way below the kart
|
||||||
|
// which is very obvious in the rescue animation.
|
||||||
|
m_kart->getKartModel()->resetVisualWheelPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset the wheels (and any other animation played for that kart)
|
|
||||||
// This avoid the effect that some wheels might be way below the kart
|
|
||||||
// which is very obvious in the rescue animation.
|
|
||||||
m_kart->getKartModel()->resetVisualWheelPosition();
|
|
||||||
|
|
||||||
} // AbstractKartAnimation
|
} // AbstractKartAnimation
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@ -70,7 +77,7 @@ AbstractKartAnimation::~AbstractKartAnimation()
|
|||||||
// is deleted (at the end of a race), which means that
|
// is deleted (at the end of a race), which means that
|
||||||
// world is in the process of being deleted. In this case
|
// world is in the process of being deleted. In this case
|
||||||
// we can't call getPhysics() anymore.
|
// we can't call getPhysics() anymore.
|
||||||
if(m_timer < 0)
|
if(m_timer < 0 && m_kart)
|
||||||
{
|
{
|
||||||
m_kart->getBody()->setAngularVelocity(btVector3(0,0,0));
|
m_kart->getBody()->setAngularVelocity(btVector3(0,0,0));
|
||||||
Physics::getInstance()->addKart(m_kart);
|
Physics::getInstance()->addKart(m_kart);
|
||||||
@ -91,7 +98,7 @@ void AbstractKartAnimation::update(float dt)
|
|||||||
m_timer -= dt;
|
m_timer -= dt;
|
||||||
if(m_timer<0)
|
if(m_timer<0)
|
||||||
{
|
{
|
||||||
m_kart->setKartAnimation(NULL);
|
if(m_kart) m_kart->setKartAnimation(NULL);
|
||||||
delete this;
|
delete this;
|
||||||
}
|
}
|
||||||
} // update
|
} // update
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include "animations/animation_base.hpp"
|
#include "animations/animation_base.hpp"
|
||||||
#include "animations/ipo.hpp"
|
#include "animations/ipo.hpp"
|
||||||
#include "animations/three_d_animation.hpp"
|
#include "animations/three_d_animation.hpp"
|
||||||
|
#include "items/flyable.hpp"
|
||||||
#include "karts/abstract_kart.hpp"
|
#include "karts/abstract_kart.hpp"
|
||||||
#include "karts/kart_properties.hpp"
|
#include "karts/kart_properties.hpp"
|
||||||
#include "modes/world.hpp"
|
#include "modes/world.hpp"
|
||||||
@ -28,7 +29,8 @@
|
|||||||
#include "LinearMath/btTransform.h"
|
#include "LinearMath/btTransform.h"
|
||||||
|
|
||||||
/** The constructor for the cannon animation.
|
/** The constructor for the cannon animation.
|
||||||
* \param kart The kart to be animated.
|
* \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
|
* \param ipo The IPO (blender interpolation curve) which the kart
|
||||||
* should follow.
|
* should follow.
|
||||||
* \param start_left, start_right: Left and right end points of the line
|
* \param start_left, start_right: Left and right end points of the line
|
||||||
@ -45,9 +47,41 @@ CannonAnimation::CannonAnimation(AbstractKart *kart, Ipo *ipo,
|
|||||||
float skid_rot)
|
float skid_rot)
|
||||||
: AbstractKartAnimation(kart, "CannonAnimation")
|
: AbstractKartAnimation(kart, "CannonAnimation")
|
||||||
{
|
{
|
||||||
m_curve = new AnimationBase(ipo);
|
m_flyable = NULL;
|
||||||
m_timer = ipo->getEndTime();
|
init(ipo, start_left, start_right, end_left, end_right, skid_rot);
|
||||||
|
} // CannonAnimation
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
/** Constructor for a flyable. It sets the kart data to NULL.
|
||||||
|
*/
|
||||||
|
CannonAnimation::CannonAnimation(Flyable *flyable, Ipo *ipo,
|
||||||
|
const Vec3 &start_left, const Vec3 &start_right,
|
||||||
|
const Vec3 &end_left, const Vec3 &end_right )
|
||||||
|
: AbstractKartAnimation(NULL, "CannonAnimation")
|
||||||
|
{
|
||||||
|
m_flyable = flyable;
|
||||||
|
init(ipo, start_left, start_right, end_left, end_right, /*skid_rot*/0);
|
||||||
|
} // CannonAnimation(Flyable*...)
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
/** Common initialisation for kart-based and flyable-based animations.
|
||||||
|
* \param ipo The IPO (blender interpolation curve) which the kart
|
||||||
|
* should follow.
|
||||||
|
* \param start_left, start_right: Left and right end points of the line
|
||||||
|
* that the kart just crossed.
|
||||||
|
* \param end_left, end_right: Left and right end points of the line at
|
||||||
|
* which the kart finishes.
|
||||||
|
* \param skid_rot Visual rotation of the kart due to skidding (while this
|
||||||
|
* value can be queried, the AbstractkartAnimation constructor
|
||||||
|
* resets the value to 0, so it needs to be passed in.
|
||||||
|
*/
|
||||||
|
void CannonAnimation::init(Ipo *ipo, const Vec3 &start_left,
|
||||||
|
const Vec3 &start_right, const Vec3 &end_left,
|
||||||
|
const Vec3 &end_right, float skid_rot)
|
||||||
|
{
|
||||||
|
m_curve = new AnimationBase(ipo);
|
||||||
|
m_timer = ipo->getEndTime();
|
||||||
|
|
||||||
// First make sure that left and right points are indeed correct
|
// First make sure that left and right points are indeed correct
|
||||||
// -------------------------------------------------------------
|
// -------------------------------------------------------------
|
||||||
Vec3 my_start_left = start_left;
|
Vec3 my_start_left = start_left;
|
||||||
@ -57,12 +91,17 @@ CannonAnimation::CannonAnimation(AbstractKart *kart, Ipo *ipo,
|
|||||||
// (the curve's origin must be in the middle of the line.
|
// (the curve's origin must be in the middle of the line.
|
||||||
m_curve->getAt(0, &p0);
|
m_curve->getAt(0, &p0);
|
||||||
m_curve->getAt(0.1f, &p1);
|
m_curve->getAt(0.1f, &p1);
|
||||||
Vec3 p2 = 0.5f*(p0 + p1) + m_kart->getNormal();
|
Vec3 p2;
|
||||||
|
if (m_kart)
|
||||||
|
p2 = 0.5f*(p0 + p1) + m_kart->getNormal();
|
||||||
|
else
|
||||||
|
p2 = 0.5f*(p0 + p1) + m_flyable->getNormal();
|
||||||
|
|
||||||
if (start_left.sideofPlane(p0, p1, p2) < 0)
|
if (start_left.sideofPlane(p0, p1, p2) < 0)
|
||||||
{
|
{
|
||||||
// Left and right start line needs to be swapped
|
// Left and right start line needs to be swapped
|
||||||
my_start_left = start_right;
|
my_start_left = start_right;
|
||||||
my_start_right = start_left;
|
my_start_right = start_left;
|
||||||
}
|
}
|
||||||
|
|
||||||
// First adjust start and end points to take on each side half the kart
|
// First adjust start and end points to take on each side half the kart
|
||||||
@ -70,8 +109,9 @@ CannonAnimation::CannonAnimation(AbstractKart *kart, Ipo *ipo,
|
|||||||
Vec3 direction = my_start_right - my_start_left;
|
Vec3 direction = my_start_right - my_start_left;
|
||||||
direction.normalize();
|
direction.normalize();
|
||||||
|
|
||||||
float kw = m_kart->getKartModel()->getWidth();
|
float kw = m_kart ? m_kart->getKartModel()->getWidth()
|
||||||
Vec3 adj_start_left = my_start_left + (0.5f*kw) * direction;
|
: m_flyable->getExtend().getX();
|
||||||
|
Vec3 adj_start_left = my_start_left + (0.5f*kw) * direction;
|
||||||
Vec3 adj_start_right = my_start_right - (0.5f*kw) * direction;
|
Vec3 adj_start_right = my_start_right - (0.5f*kw) * direction;
|
||||||
|
|
||||||
// Store the length of the start and end line, which is used
|
// Store the length of the start and end line, which is used
|
||||||
@ -99,16 +139,17 @@ CannonAnimation::CannonAnimation(AbstractKart *kart, Ipo *ipo,
|
|||||||
// This delta is rotated with the kart and added to the interpolated curve
|
// This delta is rotated with the kart and added to the interpolated curve
|
||||||
// position to get the actual kart position during the animation.
|
// position to get the actual kart position during the animation.
|
||||||
Vec3 curve_xyz;
|
Vec3 curve_xyz;
|
||||||
|
Vec3 xyz = m_kart ? m_kart->getXYZ() : m_flyable->getXYZ();
|
||||||
m_curve->update(0, &curve_xyz);
|
m_curve->update(0, &curve_xyz);
|
||||||
m_delta = kart->getXYZ() - curve_xyz;
|
m_delta = xyz - curve_xyz;
|
||||||
|
|
||||||
// Compute on which fraction of the start line the kart is, to get the
|
// Compute on which fraction of the start line the kart is, to get the
|
||||||
// second component of the kart position: distance along start line
|
// second component of the kart position: distance along start line
|
||||||
Vec3 v = adj_start_left - adj_start_right;
|
Vec3 v = adj_start_left - adj_start_right;
|
||||||
float l = v.length();
|
float l = v.length();
|
||||||
v /= l;
|
v /= l;
|
||||||
|
|
||||||
float f = v.dot(adj_start_left - kart->getXYZ());
|
float f = v.dot(adj_start_left - xyz);
|
||||||
if (f <= 0)
|
if (f <= 0)
|
||||||
f = 0;
|
f = 0;
|
||||||
else if (f >= l)
|
else if (f >= l)
|
||||||
@ -138,28 +179,36 @@ CannonAnimation::CannonAnimation(AbstractKart *kart, Ipo *ipo,
|
|||||||
Vec3 tangent;
|
Vec3 tangent;
|
||||||
m_curve->getDerivativeAt(0, &tangent);
|
m_curve->getDerivativeAt(0, &tangent);
|
||||||
// Get the current kart orientation
|
// Get the current kart orientation
|
||||||
Vec3 forward = m_kart->getTrans().getBasis().getColumn(2);
|
const btTransform &trans = m_kart ? m_kart->getTrans()
|
||||||
|
: m_flyable->getBody()->getWorldTransform();
|
||||||
|
Vec3 forward = trans.getBasis().getColumn(2);
|
||||||
Vec3 v1(tangent), v2(forward);
|
Vec3 v1(tangent), v2(forward);
|
||||||
v1.setY(0); v2.setY(0);
|
v1.setY(0); v2.setY(0);
|
||||||
m_delta_heading = shortestArcQuatNormalize2(v1, v2)
|
m_delta_heading = shortestArcQuatNormalize2(v1, v2)
|
||||||
* btQuaternion(Vec3(0,1,0), skid_rot);
|
* btQuaternion(Vec3(0, 1, 0), skid_rot);
|
||||||
|
|
||||||
|
|
||||||
// The previous call to m_curve->update will set the internal timer
|
// The previous call to m_curve->update will set the internal timer
|
||||||
// of the curve to dt. Reset it to 0 to make sure the timer is in
|
// of the curve to dt. Reset it to 0 to make sure the timer is in
|
||||||
// synch with the timer of the CanonAnimation
|
// synch with the timer of the CanonAnimation
|
||||||
m_curve->reset();
|
m_curve->reset();
|
||||||
} // CannonAnimation
|
} // init
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
CannonAnimation::~CannonAnimation()
|
CannonAnimation::~CannonAnimation()
|
||||||
{
|
{
|
||||||
delete m_curve;
|
delete m_curve;
|
||||||
|
if (m_kart)
|
||||||
btTransform pos = m_kart->getTrans();
|
{
|
||||||
m_kart->getBody()->setCenterOfMassTransform(pos);
|
btTransform pos = m_kart->getTrans();
|
||||||
Vec3 v(0, 0, m_kart->getKartProperties()->getEngineMaxSpeed());
|
m_kart->getBody()->setCenterOfMassTransform(pos);
|
||||||
m_kart->setVelocity(pos.getBasis()*v);
|
Vec3 v(0, 0, m_kart->getKartProperties()->getEngineMaxSpeed());
|
||||||
|
m_kart->setVelocity(pos.getBasis()*v);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_flyable->setAnimation(NULL);
|
||||||
|
}
|
||||||
} // ~CannonAnimation
|
} // ~CannonAnimation
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@ -184,7 +233,9 @@ void CannonAnimation::update(float dt)
|
|||||||
m_curve->getDerivativeAt(m_curve->getAnimationDuration() - m_timer,
|
m_curve->getDerivativeAt(m_curve->getAnimationDuration() - m_timer,
|
||||||
&tangent);
|
&tangent);
|
||||||
// Get the current kart orientation
|
// Get the current kart orientation
|
||||||
Vec3 forward = m_kart->getTrans().getBasis().getColumn(2);
|
const btTransform &trans = m_kart ? m_kart->getTrans()
|
||||||
|
: m_flyable->getBody()->getWorldTransform();
|
||||||
|
Vec3 forward = trans.getBasis().getColumn(2);
|
||||||
|
|
||||||
// Heading
|
// Heading
|
||||||
// -------
|
// -------
|
||||||
@ -200,10 +251,14 @@ void CannonAnimation::update(float dt)
|
|||||||
// ------------------
|
// ------------------
|
||||||
// While start and end line have to have the same 'up' vector, karts can
|
// While start and end line have to have the same 'up' vector, karts can
|
||||||
// sometimes be not parallel to them. So slowly adjust this over time
|
// sometimes be not parallel to them. So slowly adjust this over time
|
||||||
Vec3 up = m_kart->getTrans().getBasis().getColumn(1);
|
Vec3 up = trans.getBasis().getColumn(1);
|
||||||
up.normalize();
|
up.normalize();
|
||||||
Vec3 gravity = -m_kart->getBody()->getGravity();
|
Vec3 gravity = m_kart ? -m_kart->getBody()->getGravity()
|
||||||
gravity.normalize();
|
: -m_flyable->getBody()->getGravity();
|
||||||
|
if (gravity.length2() > 0)
|
||||||
|
gravity.normalize();
|
||||||
|
else
|
||||||
|
gravity.setValue(0, -1, 0);
|
||||||
// Adjust only 5% towards the real up vector. This will smoothly
|
// Adjust only 5% towards the real up vector. This will smoothly
|
||||||
// adjust the kart while the kart is in the air
|
// adjust the kart while the kart is in the air
|
||||||
Vec3 target_up_vector = (gravity*0.05f + up*0.95f).normalize();
|
Vec3 target_up_vector = (gravity*0.05f + up*0.95f).normalize();
|
||||||
@ -220,27 +275,25 @@ void CannonAnimation::update(float dt)
|
|||||||
|
|
||||||
// The timer counts backwards, so the fraction goes from 1 to 0
|
// The timer counts backwards, so the fraction goes from 1 to 0
|
||||||
float f = m_timer / m_curve->getAnimationDuration();
|
float f = m_timer / m_curve->getAnimationDuration();
|
||||||
|
|
||||||
btQuaternion zero(gravity, 0);
|
|
||||||
btQuaternion current_delta_heading = zero.slerp(m_delta_heading, f);
|
|
||||||
|
|
||||||
btQuaternion all_heading = m_kart->getRotation()*current_delta_heading*heading;
|
|
||||||
|
|
||||||
m_kart->setRotation(q_up * all_heading);
|
|
||||||
|
|
||||||
|
|
||||||
// Then compute the new location of the kart
|
|
||||||
// -----------------------------------------
|
|
||||||
float f_current_width = m_start_line_length * f
|
float f_current_width = m_start_line_length * f
|
||||||
+ m_end_line_length * (1.0f - f);
|
+ m_end_line_length * (1.0f - f);
|
||||||
|
|
||||||
// Adjust the horizontal location based on steering
|
// Then compute the new location of the kart
|
||||||
m_fraction_of_line += m_kart->getSteerPercent()*dt*2.0f;
|
// -----------------------------------------
|
||||||
btClamp(m_fraction_of_line, -1.0f, 1.0f);
|
btQuaternion all_heading;
|
||||||
|
if (m_kart)
|
||||||
|
{
|
||||||
|
btQuaternion zero(gravity, 0);
|
||||||
|
btQuaternion current_delta_heading = zero.slerp(m_delta_heading, f);
|
||||||
|
all_heading = m_kart->getRotation()*current_delta_heading*heading;
|
||||||
|
m_kart->setRotation(q_up * all_heading);
|
||||||
|
|
||||||
// horiz_delta is in kart coordinates, the rotation by q will
|
// Adjust the horizontal location based on steering
|
||||||
// transform it to the global coordinate system
|
m_fraction_of_line += m_kart->getSteerPercent()*dt*2.0f;
|
||||||
Vec3 horiz_delta = Vec3(0.5f*m_fraction_of_line * f_current_width, 0, 0);
|
btClamp(m_fraction_of_line, -1.0f, 1.0f);
|
||||||
|
} // if m_kart
|
||||||
|
else
|
||||||
|
all_heading.setValue(0, 0, 0, 1);
|
||||||
|
|
||||||
// Determine direction orthogonal to the curve for the sideway movement
|
// Determine direction orthogonal to the curve for the sideway movement
|
||||||
// of the kart.
|
// of the kart.
|
||||||
@ -251,5 +304,8 @@ void CannonAnimation::update(float dt)
|
|||||||
|
|
||||||
Vec3 curve_xyz;
|
Vec3 curve_xyz;
|
||||||
m_curve->update(dt, &curve_xyz);
|
m_curve->update(dt, &curve_xyz);
|
||||||
m_kart->setXYZ(curve_xyz+rotated_delta);
|
if (m_kart)
|
||||||
|
m_kart->setXYZ(curve_xyz + rotated_delta);
|
||||||
|
else
|
||||||
|
m_flyable->setXYZ(curve_xyz + rotated_delta);
|
||||||
} // update
|
} // update
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
|
|
||||||
class AbstractKart;
|
class AbstractKart;
|
||||||
class AnimationBase;
|
class AnimationBase;
|
||||||
|
class Flyable;
|
||||||
class Ipo;
|
class Ipo;
|
||||||
|
|
||||||
|
|
||||||
@ -46,6 +47,10 @@ protected:
|
|||||||
/** Stores the curve interpolation for the cannon. */
|
/** Stores the curve interpolation for the cannon. */
|
||||||
AnimationBase *m_curve;
|
AnimationBase *m_curve;
|
||||||
|
|
||||||
|
/** If this animation is used for a flyable (e.g. basket ball) instead
|
||||||
|
* of a kart, m_flyable is defined and m_kart is NULL. */
|
||||||
|
Flyable *m_flyable;
|
||||||
|
|
||||||
/** Length of the (adjusted, i.e. taking kart width into account)
|
/** Length of the (adjusted, i.e. taking kart width into account)
|
||||||
* start line. */
|
* start line. */
|
||||||
float m_start_line_length;
|
float m_start_line_length;
|
||||||
@ -61,12 +66,19 @@ protected:
|
|||||||
/** The initial heading of the kart when crossing the line. This is
|
/** The initial heading of the kart when crossing the line. This is
|
||||||
* used to smoothly orient the kart towards the normal of the cuve. */
|
* used to smoothly orient the kart towards the normal of the cuve. */
|
||||||
btQuaternion m_delta_heading;
|
btQuaternion m_delta_heading;
|
||||||
|
|
||||||
|
void init(Ipo *ipo, const Vec3 &start_left, const Vec3 &start_right,
|
||||||
|
const Vec3 &end_left, const Vec3 &end_right, float skid_rot);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CannonAnimation(AbstractKart *kart, Ipo *ipo,
|
CannonAnimation(AbstractKart *kart, Ipo *ipo,
|
||||||
const Vec3 &start_left, const Vec3 &start_right,
|
const Vec3 &start_left, const Vec3 &start_right,
|
||||||
const Vec3 &end_left, const Vec3 &end_right,
|
const Vec3 &end_left, const Vec3 &end_right,
|
||||||
float skid_rot);
|
float skid_rot);
|
||||||
virtual ~CannonAnimation();
|
CannonAnimation(Flyable *flyable, Ipo *ipo,
|
||||||
|
const Vec3 &start_left, const Vec3 &start_right,
|
||||||
|
const Vec3 &end_left, const Vec3 &end_right);
|
||||||
|
virtual ~CannonAnimation();
|
||||||
virtual void update(float dt);
|
virtual void update(float dt);
|
||||||
|
|
||||||
}; // CannonAnimation
|
}; // CannonAnimation
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include "graphics/show_curve.hpp"
|
#include "graphics/show_curve.hpp"
|
||||||
#include "graphics/stk_tex_manager.hpp"
|
#include "graphics/stk_tex_manager.hpp"
|
||||||
#include "io/xml_node.hpp"
|
#include "io/xml_node.hpp"
|
||||||
|
#include "items/flyable.hpp"
|
||||||
#include "karts/abstract_kart.hpp"
|
#include "karts/abstract_kart.hpp"
|
||||||
#include "karts/cannon_animation.hpp"
|
#include "karts/cannon_animation.hpp"
|
||||||
#include "karts/skidding.hpp"
|
#include "karts/skidding.hpp"
|
||||||
@ -88,9 +89,12 @@ CheckCannon::CheckCannon(const XMLNode &node, unsigned int index)
|
|||||||
: video::SColor(128, 128, 128, 128);
|
: video::SColor(128, 128, 128, 128);
|
||||||
}
|
}
|
||||||
buffer->recalculateBoundingBox();
|
buffer->recalculateBoundingBox();
|
||||||
buffer->getMaterial().setTexture(0, STKTexManager::getInstance()->getUnicolorTexture(video::SColor(128, 255, 105, 180)));
|
buffer->getMaterial().setTexture(0, STKTexManager::getInstance()
|
||||||
buffer->getMaterial().setTexture(1, STKTexManager::getInstance()->getUnicolorTexture(video::SColor(0, 0, 0, 0)));
|
->getUnicolorTexture(video::SColor(128, 255, 105, 180)));
|
||||||
buffer->getMaterial().setTexture(2, STKTexManager::getInstance()->getUnicolorTexture(video::SColor(0, 0, 0, 0)));
|
buffer->getMaterial().setTexture(1, STKTexManager::getInstance()
|
||||||
|
->getUnicolorTexture(video::SColor(0, 0, 0, 0)));
|
||||||
|
buffer->getMaterial().setTexture(2, STKTexManager::getInstance()
|
||||||
|
->getUnicolorTexture(video::SColor(0, 0, 0, 0)));
|
||||||
buffer->getMaterial().BackfaceCulling = false;
|
buffer->getMaterial().BackfaceCulling = false;
|
||||||
//mesh->setBoundingBox(buffer->getBoundingBox());
|
//mesh->setBoundingBox(buffer->getBoundingBox());
|
||||||
m_debug_target_node = irr_driver->addMesh(mesh, "checkdebug");
|
m_debug_target_node = irr_driver->addMesh(mesh, "checkdebug");
|
||||||
@ -114,6 +118,8 @@ CheckCannon::~CheckCannon()
|
|||||||
} // ~CheckCannon
|
} // ~CheckCannon
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
/** Changes the colour of a check cannon depending on state.
|
||||||
|
*/
|
||||||
void CheckCannon::changeDebugColor(bool is_active)
|
void CheckCannon::changeDebugColor(bool is_active)
|
||||||
{
|
{
|
||||||
#if defined(DEBUG) && !defined(SERVER_ONLY)
|
#if defined(DEBUG) && !defined(SERVER_ONLY)
|
||||||
@ -133,6 +139,55 @@ void CheckCannon::changeDebugColor(bool is_active)
|
|||||||
#endif
|
#endif
|
||||||
} // changeDebugColor
|
} // 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.push_back(flyable);
|
||||||
|
m_flyable_previous_position.push_back(flyable->getXYZ());
|
||||||
|
} // addFlyable
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
/** Removes a flyable from the tests if it crosses a checkline. Used when
|
||||||
|
* the flyable is removed (e.g. explodes).
|
||||||
|
*/
|
||||||
|
void CheckCannon::removeFlyable(Flyable *flyable)
|
||||||
|
{
|
||||||
|
std::vector<Flyable*>::iterator i = std::find(m_all_flyables.begin(),
|
||||||
|
m_all_flyables.end(),
|
||||||
|
flyable);
|
||||||
|
assert(i != m_all_flyables.end());
|
||||||
|
int index = i - m_all_flyables.begin(); // get the index
|
||||||
|
m_all_flyables.erase(i);
|
||||||
|
m_flyable_previous_position.erase(m_flyable_previous_position.begin() + index);
|
||||||
|
} // removeFlyable
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
/** Overriden to also check all flyables registered with the cannon.
|
||||||
|
*/
|
||||||
|
void CheckCannon::update(float dt)
|
||||||
|
{
|
||||||
|
CheckLine::update(dt);
|
||||||
|
for (unsigned int i = 0; i < m_all_flyables.size(); i++)
|
||||||
|
{
|
||||||
|
setIgnoreHeight(true);
|
||||||
|
bool triggered = isTriggered(m_flyable_previous_position[i],
|
||||||
|
m_all_flyables[i]->getXYZ(),
|
||||||
|
/*kart index - ignore*/ -1 );
|
||||||
|
setIgnoreHeight(false);
|
||||||
|
m_flyable_previous_position[i] = m_all_flyables[i]->getXYZ();
|
||||||
|
if(!triggered) continue;
|
||||||
|
|
||||||
|
// Cross the checkline - add the cannon animation
|
||||||
|
CannonAnimation *animation =
|
||||||
|
new CannonAnimation(m_all_flyables[i], m_curve->clone(),
|
||||||
|
getLeftPoint(), getRightPoint(),
|
||||||
|
m_target_left, m_target_right);
|
||||||
|
m_all_flyables[i]->setAnimation(animation);
|
||||||
|
} // for i in all flyables
|
||||||
|
} // update
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
/** Called when the check line is triggered. This function creates a cannon
|
/** Called when the check line is triggered. This function creates a cannon
|
||||||
* animation object and attaches it to the kart.
|
* animation object and attaches it to the kart.
|
||||||
|
@ -21,8 +21,10 @@
|
|||||||
|
|
||||||
#include "animations/animation_base.hpp"
|
#include "animations/animation_base.hpp"
|
||||||
#include "tracks/check_line.hpp"
|
#include "tracks/check_line.hpp"
|
||||||
|
#include "utils/cpp2011.hpp"
|
||||||
|
|
||||||
class CheckManager;
|
class CheckManager;
|
||||||
|
class Flyable;
|
||||||
class Ipo;
|
class Ipo;
|
||||||
class ShowCurve;
|
class ShowCurve;
|
||||||
class XMLNode;
|
class XMLNode;
|
||||||
@ -51,12 +53,18 @@ private:
|
|||||||
/** Used to display debug information about checklines. */
|
/** Used to display debug information about checklines. */
|
||||||
scene::IMeshSceneNode *m_debug_target_node;
|
scene::IMeshSceneNode *m_debug_target_node;
|
||||||
#endif
|
#endif
|
||||||
|
std::vector<Flyable*> m_all_flyables;
|
||||||
|
std::vector<Vec3> m_flyable_previous_position;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CheckCannon(const XMLNode &node, unsigned int index);
|
CheckCannon(const XMLNode &node, unsigned int index);
|
||||||
virtual ~CheckCannon();
|
virtual ~CheckCannon();
|
||||||
virtual void trigger(unsigned int kart_index);
|
virtual void trigger(unsigned int kart_index) OVERRIDE;
|
||||||
virtual void changeDebugColor(bool is_active);
|
virtual void changeDebugColor(bool is_active) OVERRIDE;
|
||||||
|
virtual void update(float dt) OVERRIDE;
|
||||||
|
|
||||||
|
void addFlyable(Flyable *flyable);
|
||||||
|
void removeFlyable(Flyable *flyable);
|
||||||
}; // CheckLine
|
}; // CheckLine
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -46,16 +46,16 @@ CheckCylinder::CheckCylinder(const XMLNode &node, unsigned int index, TriggerIte
|
|||||||
} // CheckCylinder
|
} // CheckCylinder
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
/** True if going from old_pos to new_pos enters or leaves this sphere. This
|
/** True if going from old_pos to new_pos enters or leaves this cylinder. This
|
||||||
* function is called from update (of the checkline structure). It also
|
* function is called from update (of the checkline structure). It also
|
||||||
* updates the flag about which karts are inside
|
* updates the flag about which karts are inside
|
||||||
* \param old_pos Position in previous frame.
|
* \param old_pos Position in previous frame.
|
||||||
* \param new_pos Position in current frame.
|
* \param new_pos Position in current frame.
|
||||||
* \param kart_id Index of the kart, can be used to store kart specific
|
* \param kart_id Index of the kart, can be used to store kart specific
|
||||||
* additional data.
|
* additional data.
|
||||||
*/
|
*/
|
||||||
bool CheckCylinder::isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
|
bool CheckCylinder::isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
|
||||||
unsigned int kart_id)
|
int kart_id)
|
||||||
{
|
{
|
||||||
// TODO: this is the code for a sphere, rewrite for cylinder
|
// TODO: this is the code for a sphere, rewrite for cylinder
|
||||||
Vec3 old_pos_xz(old_pos.x(), 0.0f, old_pos.z());
|
Vec3 old_pos_xz(old_pos.x(), 0.0f, old_pos.z());
|
||||||
|
@ -52,7 +52,7 @@ public:
|
|||||||
TriggerItemListener* listener);
|
TriggerItemListener* listener);
|
||||||
virtual ~CheckCylinder() {};
|
virtual ~CheckCylinder() {};
|
||||||
virtual bool isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
|
virtual bool isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
|
||||||
unsigned int kart_id);
|
int kart_id);
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
/** Returns if kart indx is currently inside of the sphere. */
|
/** Returns if kart indx is currently inside of the sphere. */
|
||||||
bool isInside(int index) const { return m_is_inside[index]; }
|
bool isInside(int index) const { return m_is_inside[index]; }
|
||||||
|
@ -55,7 +55,8 @@ void CheckGoal::update(float dt)
|
|||||||
|
|
||||||
if (world)
|
if (world)
|
||||||
{
|
{
|
||||||
if (isTriggered(m_previous_ball_position, world->getBallPosition(), -1))
|
if (isTriggered(m_previous_ball_position, world->getBallPosition(),
|
||||||
|
/*kart index - ignore*/-1) )
|
||||||
{
|
{
|
||||||
if (UserConfigParams::m_check_debug)
|
if (UserConfigParams::m_check_debug)
|
||||||
{
|
{
|
||||||
@ -86,7 +87,7 @@ void CheckGoal::trigger(unsigned int i)
|
|||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
bool CheckGoal::isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
|
bool CheckGoal::isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
|
||||||
unsigned int kartIndex)
|
int kart_index)
|
||||||
{
|
{
|
||||||
core::vector2df cross_point;
|
core::vector2df cross_point;
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ public:
|
|||||||
virtual void update(float dt) OVERRIDE;
|
virtual void update(float dt) OVERRIDE;
|
||||||
virtual void trigger(unsigned int kart_index) OVERRIDE;
|
virtual void trigger(unsigned int kart_index) OVERRIDE;
|
||||||
virtual bool isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
|
virtual bool isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
|
||||||
unsigned int indx) OVERRIDE;
|
int indx) OVERRIDE;
|
||||||
virtual void reset(const Track &track) OVERRIDE;
|
virtual void reset(const Track &track) OVERRIDE;
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
@ -53,13 +53,13 @@ void CheckLap::reset(const Track &track)
|
|||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
/** True if going from old_pos to new_pos crosses this checkline. This function
|
/** True if going from old_pos to new_pos crosses this checkline. This function
|
||||||
* is called from update (of the checkline structure).
|
* is called from update (of the checkline structure).
|
||||||
* \param old_pos Position in previous frame.
|
* \param old_pos Position in previous frame.
|
||||||
* \param new_pos Position in current frame.
|
* \param new_pos Position in current frame.
|
||||||
* \param kart_index Index of the kart, can be used to store kart specific
|
* \param kart_index Index of the kart, can be used to store kart specific
|
||||||
* additional data.
|
* additional data.
|
||||||
*/
|
*/
|
||||||
bool CheckLap::isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
|
bool CheckLap::isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
|
||||||
unsigned int kart_index)
|
int kart_index)
|
||||||
{
|
{
|
||||||
World* w = World::getWorld();
|
World* w = World::getWorld();
|
||||||
LinearWorld* lin_world = dynamic_cast<LinearWorld*>(w);
|
LinearWorld* lin_world = dynamic_cast<LinearWorld*>(w);
|
||||||
|
@ -40,7 +40,7 @@ public:
|
|||||||
CheckLap(const XMLNode &node, unsigned int index);
|
CheckLap(const XMLNode &node, unsigned int index);
|
||||||
virtual ~CheckLap() {};
|
virtual ~CheckLap() {};
|
||||||
virtual bool isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
|
virtual bool isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
|
||||||
unsigned int indx);
|
int indx);
|
||||||
virtual void reset(const Track &track);
|
virtual void reset(const Track &track);
|
||||||
}; // CheckLine
|
}; // CheckLine
|
||||||
|
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
CheckLine::CheckLine(const XMLNode &node, unsigned int index)
|
CheckLine::CheckLine(const XMLNode &node, unsigned int index)
|
||||||
: CheckStructure(node, index)
|
: CheckStructure(node, index)
|
||||||
{
|
{
|
||||||
|
m_ignore_height = false;
|
||||||
// Note that when this is called the karts have not been allocated
|
// Note that when this is called the karts have not been allocated
|
||||||
// in world, so we can't call world->getNumKarts()
|
// in world, so we can't call world->getNumKarts()
|
||||||
m_previous_sign.resize(race_manager->getNumberOfKarts());
|
m_previous_sign.resize(race_manager->getNumberOfKarts());
|
||||||
@ -169,13 +170,14 @@ void CheckLine::changeDebugColor(bool is_active)
|
|||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
/** True if going from old_pos to new_pos crosses this checkline. This function
|
/** True if going from old_pos to new_pos crosses this checkline. This function
|
||||||
* is called from update (of the checkline structure).
|
* is called from update (of the checkline structure).
|
||||||
* \param old_pos Position in previous frame.
|
* \param old_pos Position in previous frame.
|
||||||
* \param new_pos Position in current frame.
|
* \param new_pos Position in current frame.
|
||||||
* \param indx Index of the kart, can be used to store kart specific
|
* \param kart_indx Index of the kart, can be used to store kart specific
|
||||||
* additional data.
|
* additional data. If set to a negative number it will
|
||||||
|
* be ignored (used for e.g. soccer ball, and basket ball).
|
||||||
*/
|
*/
|
||||||
bool CheckLine::isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
|
bool CheckLine::isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
|
||||||
unsigned int kart_index)
|
int kart_index)
|
||||||
{
|
{
|
||||||
World* w = World::getWorld();
|
World* w = World::getWorld();
|
||||||
core::vector2df p=new_pos.toIrrVector2d();
|
core::vector2df p=new_pos.toIrrVector2d();
|
||||||
@ -184,7 +186,7 @@ bool CheckLine::isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
|
|||||||
|
|
||||||
bool previous_sign;
|
bool previous_sign;
|
||||||
|
|
||||||
if (kart_index == UINT_MAX)
|
if (kart_index < 0)
|
||||||
{
|
{
|
||||||
core::vector2df p = old_pos.toIrrVector2d();
|
core::vector2df p = old_pos.toIrrVector2d();
|
||||||
previous_sign = (m_line.getPointOrientation(p) >= 0);
|
previous_sign = (m_line.getPointOrientation(p) >= 0);
|
||||||
@ -196,18 +198,20 @@ bool CheckLine::isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
|
|||||||
|
|
||||||
// If the sign has changed, i.e. the infinite line was crossed somewhere,
|
// If the sign has changed, i.e. the infinite line was crossed somewhere,
|
||||||
// check if the finite line was actually crossed:
|
// check if the finite line was actually crossed:
|
||||||
|
core::vector2df cross_point;
|
||||||
if (sign != previous_sign &&
|
if (sign != previous_sign &&
|
||||||
m_line.intersectWith(core::line2df(old_pos.toIrrVector2d(),
|
m_line.intersectWith(core::line2df(old_pos.toIrrVector2d(),
|
||||||
new_pos.toIrrVector2d()),
|
new_pos.toIrrVector2d()),
|
||||||
m_cross_point) )
|
cross_point) )
|
||||||
{
|
{
|
||||||
// Now check the minimum height: the kart position must be within a
|
// Now check the minimum height: the kart position must be within a
|
||||||
// reasonable distance in the Z axis - 'reasonable' for now to be
|
// reasonable distance in the Z axis - 'reasonable' for now to be
|
||||||
// between -1 and 4 units (negative numbers are unlikely, but help
|
// between -1 and 4 units (negative numbers are unlikely, but help
|
||||||
// in case that the kart is 'somewhat' inside of the track, or the
|
// in case that the kart is 'somewhat' inside of the track, or the
|
||||||
// checklines are a bit off in Z direction.
|
// checklines are a bit off in Z direction.
|
||||||
result = new_pos.getY()-m_min_height<m_over_min_height &&
|
result = m_ignore_height ||
|
||||||
new_pos.getY()-m_min_height>-m_under_min_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(World::getWorld()->getNumKarts()>0)
|
||||||
@ -219,20 +223,20 @@ bool CheckLine::isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
|
|||||||
Log::info("CheckLine", "Kart %d crosses line, but wrong height "
|
Log::info("CheckLine", "Kart %d crosses line, but wrong height "
|
||||||
"(%f vs %f).",
|
"(%f vs %f).",
|
||||||
kart_index, new_pos.getY(), m_min_height);
|
kart_index, new_pos.getY(), m_min_height);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
result = false;
|
result = false;
|
||||||
|
|
||||||
if (kart_index != UINT_MAX)
|
if (kart_index >= 0)
|
||||||
m_previous_sign[kart_index] = sign;
|
|
||||||
|
|
||||||
if (result && kart_index != UINT_MAX)
|
|
||||||
{
|
{
|
||||||
LinearWorld* lw = dynamic_cast<LinearWorld*>(w);
|
m_previous_sign[kart_index] = sign;
|
||||||
if (lw != NULL)
|
if (result)
|
||||||
lw->setLastTriggeredCheckline(kart_index, m_index);
|
{
|
||||||
|
LinearWorld* lw = dynamic_cast<LinearWorld*>(w);
|
||||||
|
if (lw != NULL)
|
||||||
|
lw->setLastTriggeredCheckline(kart_index, m_index);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
} // isTriggered
|
} // isTriggered
|
||||||
|
@ -46,7 +46,10 @@ private:
|
|||||||
/** The line that is tested for being crossed. */
|
/** The line that is tested for being crossed. */
|
||||||
core::line2df m_line;
|
core::line2df m_line;
|
||||||
|
|
||||||
core::vector2df m_cross_point;
|
/** True if this line should ignore the height test. This is required
|
||||||
|
* e.g. for basketball cannons, since the ball can be too height to
|
||||||
|
* otherwise trigger the cannon. */
|
||||||
|
bool m_ignore_height;
|
||||||
|
|
||||||
/** The minimum height of the checkline. */
|
/** The minimum height of the checkline. */
|
||||||
float m_min_height;
|
float m_min_height;
|
||||||
@ -79,17 +82,18 @@ public:
|
|||||||
CheckLine(const XMLNode &node, unsigned int index);
|
CheckLine(const XMLNode &node, unsigned int index);
|
||||||
virtual ~CheckLine();
|
virtual ~CheckLine();
|
||||||
virtual bool isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
|
virtual bool isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
|
||||||
unsigned int indx);
|
int indx);
|
||||||
virtual void reset(const Track &track);
|
virtual void reset(const Track &track);
|
||||||
virtual void resetAfterKartMove(unsigned int kart_index);
|
virtual void resetAfterKartMove(unsigned int kart_index);
|
||||||
virtual void changeDebugColor(bool is_active);
|
virtual void changeDebugColor(bool is_active);
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
/** Returns the actual line data for this checkpoint. */
|
/** Returns the actual line data for this checkpoint. */
|
||||||
const core::line2df &getLine2D() const {return m_line;}
|
const core::line2df &getLine2D() const {return m_line;}
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
/** Returns the 2d point at which the line was crossed. Note that this
|
/** Sets if this check line should not do a height test for testing
|
||||||
* value is ONLY valid after isTriggered is called and inside of
|
* if a line is crossed. Used for basket calls in cannon (the ball can
|
||||||
* trigger(). */
|
* be too heigh to otherwise trigger he cannon). */
|
||||||
const core::vector2df &getCrossPoint() const { return m_cross_point; }
|
void setIgnoreHeight(bool b) { m_ignore_height = b; }
|
||||||
}; // CheckLine
|
}; // CheckLine
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -131,6 +131,37 @@ void CheckManager::resetAfterKartMove(AbstractKart *kart)
|
|||||||
(*i)->resetAfterKartMove(kart->getWorldKartId());
|
(*i)->resetAfterKartMove(kart->getWorldKartId());
|
||||||
} // resetAfterKartMove
|
} // resetAfterKartMove
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
/** Adds a flyable object to be tested against cannons. This will allow
|
||||||
|
* bowling- and rubber-balls to fly in a cannon.
|
||||||
|
* \param flyable Pointer to the flyable to be added.
|
||||||
|
*/
|
||||||
|
void CheckManager::addFlyableToCannons(Flyable *flyable)
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < m_all_checks.size(); i++)
|
||||||
|
{
|
||||||
|
CheckCannon *cc = dynamic_cast<CheckCannon*>(m_all_checks[i]);
|
||||||
|
if (cc)
|
||||||
|
cc->addFlyable(flyable);
|
||||||
|
}
|
||||||
|
} // addFlyable
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
/** Removes a flyable from all cannons. Used when this flyable is removed
|
||||||
|
* (e.g. explodes).
|
||||||
|
* \param flyable Pointer to the flyable to be removed.
|
||||||
|
*/
|
||||||
|
void CheckManager::removeFlyableFromCannons(Flyable *flyable)
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < m_all_checks.size(); i++)
|
||||||
|
{
|
||||||
|
CheckCannon *cc = dynamic_cast<CheckCannon*>(m_all_checks[i]);
|
||||||
|
if (cc)
|
||||||
|
cc->removeFlyable(flyable);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // addFlyable
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
/** Updates all animations. Called one per time step.
|
/** Updates all animations. Called one per time step.
|
||||||
* \param dt Time since last call.
|
* \param dt Time since last call.
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
class AbstractKart;
|
class AbstractKart;
|
||||||
class CheckStructure;
|
class CheckStructure;
|
||||||
|
class Flyable;
|
||||||
class Track;
|
class Track;
|
||||||
class XMLNode;
|
class XMLNode;
|
||||||
class Vec3;
|
class Vec3;
|
||||||
@ -46,6 +47,8 @@ private:
|
|||||||
~CheckManager();
|
~CheckManager();
|
||||||
public:
|
public:
|
||||||
void add(CheckStructure* strct) { m_all_checks.push_back(strct); }
|
void add(CheckStructure* strct) { m_all_checks.push_back(strct); }
|
||||||
|
void addFlyableToCannons(Flyable *flyable);
|
||||||
|
void removeFlyableFromCannons(Flyable *flyable);
|
||||||
void load(const XMLNode &node);
|
void load(const XMLNode &node);
|
||||||
void update(float dt);
|
void update(float dt);
|
||||||
void reset(const Track &track);
|
void reset(const Track &track);
|
||||||
|
@ -53,11 +53,11 @@ CheckSphere::CheckSphere(const XMLNode &node, unsigned int index)
|
|||||||
* updates the flag about which karts are inside
|
* updates the flag about which karts are inside
|
||||||
* \param old_pos Position in previous frame.
|
* \param old_pos Position in previous frame.
|
||||||
* \param new_pos Position in current frame.
|
* \param new_pos Position in current frame.
|
||||||
* \param kart_id Index of the kart, can be used to store kart specific
|
* \param kart_id Index of the kart, can be used to store kart specific
|
||||||
* additional data.
|
* additional data.
|
||||||
*/
|
*/
|
||||||
bool CheckSphere::isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
|
bool CheckSphere::isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
|
||||||
unsigned int kart_id)
|
int kart_id)
|
||||||
{
|
{
|
||||||
float old_dist2 = (old_pos-m_center_point).length2();
|
float old_dist2 = (old_pos-m_center_point).length2();
|
||||||
float new_dist2 = (new_pos-m_center_point).length2();
|
float new_dist2 = (new_pos-m_center_point).length2();
|
||||||
|
@ -48,7 +48,7 @@ public:
|
|||||||
CheckSphere(const XMLNode &node, unsigned int index);
|
CheckSphere(const XMLNode &node, unsigned int index);
|
||||||
virtual ~CheckSphere() {};
|
virtual ~CheckSphere() {};
|
||||||
virtual bool isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
|
virtual bool isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
|
||||||
unsigned int kart_id);
|
int kart_id);
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
/** Returns if kart indx is currently inside of the sphere. */
|
/** Returns if kart indx is currently inside of the sphere. */
|
||||||
bool isInside(int index) const { return m_is_inside[index]; }
|
bool isInside(int index) const { return m_is_inside[index]; }
|
||||||
|
@ -115,7 +115,7 @@ public:
|
|||||||
* additional data.
|
* additional data.
|
||||||
*/
|
*/
|
||||||
virtual bool isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
|
virtual bool isTriggered(const Vec3 &old_pos, const Vec3 &new_pos,
|
||||||
unsigned int indx)=0;
|
int indx)=0;
|
||||||
virtual void trigger(unsigned int kart_index);
|
virtual void trigger(unsigned int kart_index);
|
||||||
virtual void reset(const Track &track);
|
virtual void reset(const Track &track);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user