diff --git a/data/stk_config.xml b/data/stk_config.xml
index 5627442b9..4133007d7 100644
--- a/data/stk_config.xml
+++ b/data/stk_config.xml
@@ -222,6 +222,11 @@
the force a plunger/rubber band applies to the kart(s).
duration is the duration a rubber band acts. -->
+
+
+
diff --git a/src/Makefile.am b/src/Makefile.am
index aca619e3f..4dcc6dc85 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -158,6 +158,8 @@ supertuxkart_SOURCES = \
karts/controller/default_ai_controller.hpp \
karts/controller/end_controller.cpp \
karts/controller/end_controller.hpp \
+ karts/explosion_animation.cpp \
+ karts/explosion_animation.hpp \
karts/controller/kart_control.hpp \
karts/controller/new_ai_controller.cpp \
karts/controller/new_ai_controller.hpp \
diff --git a/src/ide/vc9/supertuxkart.vcproj b/src/ide/vc9/supertuxkart.vcproj
index d3c1d11b2..32d279a54 100644
--- a/src/ide/vc9/supertuxkart.vcproj
+++ b/src/ide/vc9/supertuxkart.vcproj
@@ -464,6 +464,10 @@
+
+
@@ -1286,6 +1290,10 @@
+
+
diff --git a/src/input/input_manager.cpp b/src/input/input_manager.cpp
index 593b499d6..2ac819595 100644
--- a/src/input/input_manager.cpp
+++ b/src/input/input_manager.cpp
@@ -105,6 +105,7 @@ void InputManager::handleStaticAction(int key, int value)
{
Kart* kart = world->getLocalPlayerKart(0);
kart->setPowerup(POWERUP_BUBBLEGUM, 10000);
+ kart->handleExplosion(kart->getXYZ(), true);
}
break;
case KEY_F2:
diff --git a/src/karts/explosion_animation.cpp b/src/karts/explosion_animation.cpp
new file mode 100644
index 000000000..3040be1ee
--- /dev/null
+++ b/src/karts/explosion_animation.cpp
@@ -0,0 +1,101 @@
+// $Id$
+//
+// SuperTuxKart - a fun racing game with go-kart
+// Copyright (C) 2010 Joerg Henrichs
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 3
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#include "karts/explosion_animation.hpp"
+
+#include "karts/kart.hpp"
+#include "modes/world.hpp"
+#include "tracks/track.hpp"
+#include "utils/constants.hpp"
+
+Vec3 m_add_rotation;
+Vec3 m_curr_rotation;
+
+/** The constructor stores a pointer to the kart this object is animating,
+ * and initialised the timer.
+ * \param kart Pointer to the kart which is animated.
+ */
+ExplosionAnimation::ExplosionAnimation(Kart *kart)
+{
+ m_timer = -1;
+ m_kart = kart;
+}; // ExplosionAnimation
+
+// ----------------------------------------------------------------------------
+/** Starts an explosion animation.
+ * \param pos The coordinates of the explosion.
+ * \param direct_hig True if the kart was hit directly --> maximal impact.
+ */
+void ExplosionAnimation::handleExplosion(const Vec3 &pos, bool direct_hit)
+{
+ // Avoid doing another explosion while a kart is thrown around in the air.
+ if(m_timer>=0) return;
+
+ m_timer = 0;
+ m_xyz = m_kart->getXYZ();
+
+ float t = m_kart->getKartProperties()->getExplosionTime();
+
+ // Half of the overall time is spent in raising, so only use
+ // half of the explosion time here.
+ // Velocity after t seconds is:
+ // v(t) = m_up_velocity + t*gravity
+ // Since v(explosion_time*0.5) = 0, the following forumla computes
+ // the right initial velocity for a kart to land back after
+ // the specified time.
+ m_up_velocity = 0.5f * t * World::getWorld()->getTrack()->getGravity();
+ World::getWorld()->getPhysics()->removeKart(m_kart);
+
+ m_curr_rotation.setHPR(m_kart->getRotation());
+ const int max_rotation = direct_hit ? 2 : 1;
+ // To get rotations in botb directions for each axis we determine a random
+ // number between -(max_rotation-1) and +(max_rotation-1)
+ float f=2.0f*M_PI/t;
+ m_add_rotation.setHeading( (rand()%(2*max_rotation+1)-max_rotation)*f );
+ m_add_rotation.setPitch( (rand()%(2*max_rotation+1)-max_rotation)*f );
+ m_add_rotation.setRoll( (rand()%(2*max_rotation+1)-max_rotation)*f );
+
+} // handleExplosion
+
+// ----------------------------------------------------------------------------
+/** Updates the explosion animation.
+ * \param dt Time step size.
+ * \return True if the explosion is still shown, false if it has finished.
+ */
+bool ExplosionAnimation::update(float dt)
+{
+ assert(m_timer>=0);
+ m_timer += dt;
+ if(m_timer>m_kart->getKartProperties()->getExplosionTime())
+ {
+ m_timer=-1;
+ World::getWorld()->getPhysics()->addKart(m_kart);
+ m_kart->getBody()->setLinearVelocity(btVector3(0,0,0));
+ m_kart->getBody()->setAngularVelocity(btVector3(0,0,0));
+ return false;
+ }
+ m_up_velocity -= dt*World::getWorld()->getTrack()->getGravity();
+ m_xyz.setY(m_xyz.getY()+m_up_velocity*dt);
+ m_kart->setXYZ(m_xyz);
+ m_curr_rotation += dt*m_add_rotation;
+ btQuaternion q(m_curr_rotation.getHeading(), m_curr_rotation.getPitch(),
+ m_curr_rotation.getRoll());
+ m_kart->setRotation(q);
+ return true;
+} // update
\ No newline at end of file
diff --git a/src/karts/explosion_animation.hpp b/src/karts/explosion_animation.hpp
new file mode 100644
index 000000000..3235d1ca4
--- /dev/null
+++ b/src/karts/explosion_animation.hpp
@@ -0,0 +1,66 @@
+// $Id$
+//
+// SuperTuxKart - a fun racing game with go-kart
+// Copyright (C) 2010 Joerg Henrichs
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 3
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#ifndef HEADER_EXPLOSION_ANIMATION_HPP
+#define HEADER_EXPLOSION_ANIMATION_HPP
+
+#include "utils/vec3.hpp"
+
+class Kart;
+
+/** This class is a 'mixin' for kart, and handles the animated explosion.
+ * I.e. it will throw the kart a certain amount in the air, rotate it
+ * randomly, and after the specified time period let it land at the
+ * same spot where it was hit, therefore avoiding any problems of
+ * karts being pushed on wrong parts of the track, and making explosion
+ * more 'fair' (it can't happen that one explosion give you actually
+ * a benefit by pushing you forwards.
+ * The object is a base class for kart, but will only be used if an
+ * explosion happens.
+ */
+class ExplosionAnimation
+{
+private:
+ /** The coordinates where the kart was hit originally. */
+ Vec3 m_xyz;
+
+ /** The rotation of the kart at the time of the explosion. */
+ Vec3 m_hpr;
+
+ /** The upwards velocity. */
+ float m_up_velocity;
+
+ /** Timer for the explosion. */
+ float m_timer;
+
+ /** Duration for this explosion. This can potentially be set
+ * with different values for different karts, or depending
+ * on difficulty (so that on easy you can drive again earlier. */
+ float m_duration;
+
+ /** A pointer to the class to which this object belongs. */
+ Kart *m_kart;
+
+public:
+ ExplosionAnimation(Kart *kart);
+ ~ExplosionAnimation() {};
+ void handleExplosion(const Vec3& pos, bool direct_hit);
+ bool update(float dt);
+}; // ExplosionAnimation
+#endif
diff --git a/src/karts/kart.cpp b/src/karts/kart.cpp
index 7ade116a1..2860ae49a 100644
--- a/src/karts/kart.cpp
+++ b/src/karts/kart.cpp
@@ -64,7 +64,7 @@
Kart::Kart (const std::string& ident, int position,
const btTransform& init_transform)
: TerrainInfo(1),
- Moveable(), m_powerup(this)
+ Moveable(), ExplosionAnimation(this), m_powerup(this)
#if defined(WIN32) && !defined(__CYGWIN__)
# pragma warning(1:4355)
@@ -600,12 +600,15 @@ float Kart::getActualWheelForce()
} // getActualWheelForce
//-----------------------------------------------------------------------------
-/** The kart is on ground if all 4 wheels touch the ground.
+/** The kart is on ground if all 4 wheels touch the ground, and if no special
+ * animation (rescue or explosion) is happening).
*/
bool Kart::isOnGround() const
{
- return (m_vehicle->getNumWheelsOnGround() == m_vehicle->getNumWheels());
+ return (m_vehicle->getNumWheelsOnGround() == m_vehicle->getNumWheels()
+ && m_kart_mode!=KM_RESCUE && m_kart_mode!=KM_EXPLOSION);
} // isOnGround
+
//-----------------------------------------------------------------------------
/** The kart is near the ground, but not necesarily on it (small jumps). This
* is used to determine when to switch off the upright constraint, so that
@@ -618,6 +621,7 @@ bool Kart::isNearGround() const
else
return ((getXYZ().getZ() - getHoT()) < stk_config->m_near_ground);
} // isNearGround
+
//-----------------------------------------------------------------------------
/** Called when an explosion happens.
* \param pos Position of the explosion.
@@ -629,8 +633,13 @@ void Kart::handleExplosion(const Vec3& pos, bool direct_hit)
int sign_bits = rand(); // To select plus or minus randomnly, assuming 15 bit at least
if(direct_hit)
{
+ printf("he: ");
+ ExplosionAnimation::handleExplosion(pos, direct_hit);
+ m_kart_mode = KM_EXPLOSION;
// Play associated kart sound
playCustomSFX(SFXManager::CUSTOM_EXPLODE);
+ return;
+
float sign_a = (sign_bits & (0x1 << 8)) ? 1.0f : -1.0f;
float sign_b = (sign_bits & (0x1 << 9)) ? 1.0f : -1.0f;
float sign_c = (sign_bits & (0x1 << 10)) ? 1.0f : -1.0f;
@@ -755,6 +764,12 @@ void Kart::update(float dt)
0));
setRotation(getRotation()*q_roll*q_pitch);
} // if rescue mode
+ else if ( m_kart_mode==KM_EXPLOSION)
+ {
+ if(!ExplosionAnimation::update(dt))
+ m_kart_mode = KM_RACE;
+ }
+
m_attachment->update(dt);
//smoke drawing control point
@@ -764,6 +779,9 @@ void Kart::update(float dt)
m_water_splash_system->update(dt);
m_nitro->update(dt);
m_slip_stream->update(dt);
+ // update star effect (call will do nothing if stars are not activated)
+ m_stars_effect->update(dt);
+
} // UserConfigParams::m_graphical_effects
updatePhysics(dt);
@@ -1319,8 +1337,6 @@ void Kart::updatePhysics(float dt)
);
#endif
- // update star effect (call will do nothing if stars are not activated)
- m_stars_effect->update(dt);
} // updatePhysics
//-----------------------------------------------------------------------------
diff --git a/src/karts/kart.hpp b/src/karts/kart.hpp
index d9463cae0..93ea11d51 100644
--- a/src/karts/kart.hpp
+++ b/src/karts/kart.hpp
@@ -26,6 +26,7 @@
#include "graphics/camera.hpp"
#include "items/attachment.hpp"
#include "items/powerup.hpp"
+#include "karts/explosion_animation.hpp"
#include "karts/moveable.hpp"
#include "karts/kart_properties.hpp"
#include "karts/controller/controller.hpp"
@@ -55,7 +56,7 @@ class Stars;
* is an object that is moved on the track, and has position and rotations)
* and TerrainInfo, which manages the terrain the kart is on.
*/
-class Kart : public TerrainInfo, public Moveable
+class Kart : public TerrainInfo, public Moveable, public ExplosionAnimation
{
private:
/** Reset position. */
diff --git a/src/karts/kart_properties.cpp b/src/karts/kart_properties.cpp
index 7ddc14491..7d6ba2016 100644
--- a/src/karts/kart_properties.cpp
+++ b/src/karts/kart_properties.cpp
@@ -72,7 +72,8 @@ KartProperties::KartProperties(const std::string &filename) : m_icon_material(0)
m_slipstream_length = m_slipstream_collect_time =
m_slipstream_use_time = m_slipstream_add_power =
m_slipstream_min_speed = m_camera_distance =
- m_rescue_time = m_rescue_height = UNDEFINED;
+ m_rescue_time = m_rescue_height = m_explosion_time =
+ m_explosion_height = UNDEFINED;
m_gravity_center_shift = Vec3(UNDEFINED);
m_has_skidmarks = true;
m_version = 0;
@@ -214,6 +215,12 @@ void KartProperties::getAllData(const XMLNode * root)
rescue_node->get("height", &m_rescue_height );
}
+ if(const XMLNode *explosion_node = root->getNode("explosion"))
+ {
+ explosion_node->get("time", &m_explosion_time );
+ explosion_node->get("height", &m_explosion_height);
+ }
+
if(const XMLNode *skid_node = root->getNode("skid"))
{
skid_node->get("increase", &m_skid_increase );
@@ -469,6 +476,8 @@ void KartProperties::checkAllSet(const std::string &filename)
CHECK_NEG(m_rescue_height, "rescue height" );
CHECK_NEG(m_rescue_time, "rescue time" );
CHECK_NEG(m_rescue_vert_offset, "rescue vert-offset" );
+ CHECK_NEG(m_explosion_time, "explosion time" );
+ CHECK_NEG(m_explosion_height, "explosion height" );
} // checkAllSet
diff --git a/src/karts/kart_properties.hpp b/src/karts/kart_properties.hpp
index 57be24082..da99bac7a 100644
--- a/src/karts/kart_properties.hpp
+++ b/src/karts/kart_properties.hpp
@@ -112,6 +112,12 @@ private:
/** Distance the kart is raised before dropped. */
float m_rescue_height;
+ /** Time an animated explosion is shown. Longer = more delay for kart. */
+ float m_explosion_time;
+
+ /** Height of an explosion animation. */
+ float m_explosion_height;
+
/** Vertical offset after rescue. */
float m_rescue_vert_offset;
@@ -247,8 +253,16 @@ public:
float getRescueTime () const {return m_rescue_time; }
/** Returns the height a kart is moved to during a rescue. */
float getRescueHeight () const {return m_rescue_height; }
+ /** Returns the time an explosion animation is shown. */
+ float getExplosionTime () const {return m_explosion_time; }
+ /** Returns the height of the explosion animation. */
+ float getExplosionHeight () const {return m_explosion_height; }
+ /** Returns how much a kart can roll/pitch before the upright constraint
+ * counteracts. */
float getUprightTolerance () const {return m_upright_tolerance; }
+ /** Returns the maximum value of the upright counteracting force. */
float getUprightMaxForce () const {return m_upright_max_force; }
+ /** Returns artificial acceleration to keep wheels on track. */
float getTrackConnectionAccel () const {return m_track_connection_accel; }
/** Returns the maximum length of a rubber band before it breaks. */
float getRubberBandMaxLength () const {return m_rubber_band_max_length; }
diff --git a/src/karts/moveable.cpp b/src/karts/moveable.cpp
index 8ccc60db9..65a17e78f 100644
--- a/src/karts/moveable.cpp
+++ b/src/karts/moveable.cpp
@@ -94,6 +94,10 @@ void Moveable::reset()
} // reset
//-----------------------------------------------------------------------------
+/** Updates the current position and rotation from the corresponding physics
+ * body, and then calls updateGraphics to position the model correctly.
+ * \param float dt Time step size.
+ */
void Moveable::update(float dt)
{
m_motion_state->getWorldTransform(m_transform);
@@ -113,6 +117,11 @@ void Moveable::update(float dt)
} // update
//-----------------------------------------------------------------------------
+/** Creates the bullet rigid body for this moveable.
+ * \param mass Mass of this object.
+ * \param trans Transform (=position and orientation) for this object).
+ * \param shape Bullet collision shape for this object.
+ */
void Moveable::createBody(float mass, btTransform& trans,
btCollisionShape *shape) {
btVector3 inertia;