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;