First proper working version of cannon.

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@11168 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk 2012-04-26 22:17:46 +00:00
parent a4ba8d2162
commit 02dc97a021
4 changed files with 74 additions and 70 deletions

View File

@ -27,18 +27,37 @@
#include "LinearMath/btTransform.h"
CannonAnimation::CannonAnimation(AbstractKart *kart, Ipo *ipo,
const Vec3 &delta)
CannonAnimation::CannonAnimation(AbstractKart *kart, Ipo *ipo)
: AbstractKartAnimation(kart, "CannonAnimation")
{
m_curve = new AnimationBase(ipo);
m_timer = ipo->getEndTime();
Vec3 xyz = m_kart->getXYZ();
Vec3 hpr, scale;
// Get the curve position at t=0
m_curve->update(0, &xyz, &hpr, &scale);
m_offset = m_kart->getXYZ() - xyz-delta;
m_delta = delta;
// Compute the delta between the kart position and the start of the curve.
// This delta is rotated with the kart and added to the interpolated curve
// position to get the actual kart position during the animation.
m_curve->update(0, &m_previous_orig_xyz);
m_delta = kart->getXYZ() - m_previous_orig_xyz;
// Now the delta vector needs to be rotated back, so that it will point
// in the right direction when it is (in update) rotated to be the same
// as the kart's heading. To estimate the angle at the start, use the
// interpolated value at t=dt:
const float dt = 0.1f;
Vec3 xyz1;
m_curve->update(dt, &xyz1);
core::vector3df rot1 = (xyz1-m_previous_orig_xyz).toIrrVector()
.getHorizontalAngle();
core::vector3df rot = (m_previous_orig_xyz-xyz1).toIrrVector()
.getHorizontalAngle();
btQuaternion q(Vec3(0,1,0),rot.Y*DEGREE_TO_RAD);
btMatrix3x3 m(q);
m_delta = m * m_delta;
// 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
// synch with the timer of the CanonAnimation
m_curve->reset();
} // CannonAnimation
// ----------------------------------------------------------------------------
@ -48,9 +67,10 @@ CannonAnimation::~CannonAnimation()
float epsilon = 0.5f * m_kart->getKartHeight();
btTransform pos;
pos.setOrigin(m_kart->getXYZ()+btVector3(0, m_kart->getKartHeight() + epsilon,
0));
pos.setRotation(btQuaternion(btVector3(0.0f, 1.0f, 0.0f), m_kart->getHeading()));
pos.setOrigin(m_kart->getXYZ()
+btVector3(0, m_kart->getKartHeight() + epsilon, 0) );
pos.setRotation(btQuaternion(btVector3(0.0f, 1.0f, 0.0f),
m_kart->getHeading() ));
m_kart->getBody()->setCenterOfMassTransform(pos);
Vec3 v(0, 0, m_kart->getKartProperties()->getMaxSpeed());
@ -69,18 +89,26 @@ void CannonAnimation::update(float dt)
AbstractKartAnimation::update(dt);
return;
}
Vec3 xyz = m_kart->getXYZ();
core::vector3df old_xyz = xyz.toIrrVector();
Vec3 hpr, scale;
m_curve->update(dt, &xyz, &hpr, &scale);
Vec3 xyz;
m_curve->update(dt, &xyz);
// It can happen that the same position is returned, e.g. if the end of
// the curve is reached, but due to floating point differences the
// end is not detected in the above test. To avoid that the kart then
// rotates to a heading of 0, do not rotate in this case at all, i.e.
// the previous rotation is kept.
if(xyz!=m_previous_orig_xyz)
{
core::vector3df rot = (xyz-m_previous_orig_xyz).toIrrVector()
.getHorizontalAngle();
btQuaternion q(Vec3(0,1,0),rot.Y*DEGREE_TO_RAD);
m_kart->setRotation(q);
}
m_previous_orig_xyz = xyz;
Vec3 rotated_delta = m_kart->getTrans().getBasis()*m_delta;
rotated_delta = Vec3(0,0,0);
Vec3 new_xyz = xyz+rotated_delta+m_offset;
m_kart->setXYZ(new_xyz);
m_kart->setXYZ(xyz + rotated_delta);
core::vector3df rot = (new_xyz.toIrrVector()-old_xyz).getHorizontalAngle();
btQuaternion q(Vec3(0,1,0),rot.Y*DEGREE_TO_RAD);
m_kart->setRotation(q);
AbstractKartAnimation::update(dt);
} // update

View File

@ -34,21 +34,21 @@ class Ipo;
class CannonAnimation: public AbstractKartAnimation
{
protected:
/** The offset between the origin of the curve (relative to which
* all points are interpolated) and the position of the kart. */
Vec3 m_offset;
/** An offset that is rotated with the kart and is added to the
* interpolated point. This basically shifts the curve (usually)
* to the left/right to be aligned with the crossing point of the
* kart. */
/** This is the difference between the position of the kart when the
* cannon line is crossed and the curve interpolation at t=0. This
* is added to each interpolated curve value to give the final
* kart position (so the kart moves relative to the curve). */
Vec3 m_delta;
/** Stores the curve interpolation for the cannon. */
AnimationBase *m_curve;
/** This stores the original (unmodified) interpolated curve value. THis
* is used to determine the orientation of the kart. */
Vec3 m_previous_orig_xyz;
public:
CannonAnimation(AbstractKart *kart, Ipo *ipo, const Vec3 &delta);
CannonAnimation(AbstractKart *kart, Ipo *ipo);
virtual ~CannonAnimation();
virtual void update(float dt);

View File

@ -26,20 +26,6 @@
#include "modes/world.hpp"
CheckCannon::CannonCurve::CannonCurve(const XMLNode &node)
: AnimationBase(node)
{
m_speed = -1;
node.get("speed", &m_speed);
} // CannonCurve
// ------------------------------------------------------------------------
void CheckCannon::CannonCurve::update(float dt)
{
} // update
// ============================================================================
/** Constructor for a check cannon.
* \param node XML node containing the parameters for this checkline.
* \param index Index of this check structure in the check manager.
@ -49,30 +35,34 @@ CheckCannon::CheckCannon(const XMLNode &node, unsigned int index)
{
core::vector3df p1, p2;
if(!node.get("target-p1", &p1) ||
!node.get("target-p2", &p2) )
{
printf("CheckCannon has no target line specified.\n");
exit(-1);
}
!node.get("target-p2", &p2) )
{
printf("CheckCannon has no target line specified.\n");
exit(-1);
}
m_target.setLine(p1, p2);
m_curve = new Ipo(*(node.getNode("curve")));
} // CheckCannon
// ----------------------------------------------------------------------------
/** Destructor, frees the curve data (which the cannon animation objects only
* have a read-only copy of).
*/
CheckCannon::~CheckCannon()
{
delete m_curve;
} // ~CheckCannon
// ----------------------------------------------------------------------------
/** 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)
{
Vec3 target(m_target.getMiddle());
AbstractKart *kart = World::getWorld()->getKart(kart_index);
Vec3 target(m_target.getMiddle());
AbstractKart *kart = World::getWorld()->getKart(kart_index);
if(kart->getKartAnimation()) return;
const core::vector2df &cross = getCrossPoint();
const core::line2df &line = getLine2D();
Vec3 delta = Vec3(1,0,0) * (line.start-cross).getLength();
new CannonAnimation(kart, m_curve->clone(), delta);
new CannonAnimation(kart, m_curve->clone());
} // CheckCannon

View File

@ -38,20 +38,6 @@ private:
/** The target point the kart will fly to. */
core::line3df m_target;
// ------------------------------------------------------------------------
protected:
class CannonCurve : public AnimationBase
{
private:
/** The speed with which the kart moves. */
float m_speed;
public:
CannonCurve(const XMLNode &node);
void update(float dt);
}; // CannonCurve
// ------------------------------------------------------------------------
/** Stores the cannon curve data. */
Ipo *m_curve;