From eca5b3e570cd1067c5d21cf68fc50156e58b74d2 Mon Sep 17 00:00:00 2001 From: hikerstk Date: Sun, 1 Apr 2012 22:57:41 +0000 Subject: [PATCH] Refactored handling of kart animations: instead of using a fixed object in the kart, now each animation (rescue, explosion, canon) has its own object and implementation using a common interface. This simplifies AbstractKartInterface, and makes it easier to add new functionailty. Instead of using: kart->rescue(...), or kart->explode(...) you use new ExplosionAnimation(kart, ...) etc. Memory handling is done by the object (and abstract kart). git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@11070 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/graphics/camera.cpp | 3 +- src/graphics/slip_stream.cpp | 6 +- src/ide/vc9/supertuxkart.vcproj | 40 ++++- src/items/attachment.cpp | 9 +- src/items/flyable.cpp | 8 +- src/items/swatter.cpp | 3 +- src/karts/abstract_kart.cpp | 36 +++++ src/karts/abstract_kart.hpp | 32 ++-- src/karts/abstract_kart_animation.cpp | 48 ++++++ src/karts/abstract_kart_animation.hpp | 61 ++++++++ src/karts/canon_animation.cpp | 72 +++++++++ src/karts/canon_animation.hpp | 61 ++++++++ .../controller/default_ai_controller.cpp | 9 +- src/karts/controller/end_controller.cpp | 5 +- src/karts/controller/new_ai_controller.cpp | 7 +- src/karts/controller/player_controller.cpp | 7 +- src/karts/explosion_animation.cpp | 135 +++++++++++++++++ src/karts/explosion_animation.hpp | 70 +++++++++ src/karts/kart.cpp | 143 ++++++++---------- src/karts/kart.hpp | 34 ++--- src/karts/kart_animation.cpp | 44 +----- src/karts/kart_animation.hpp | 26 +--- src/karts/kart_with_stats.cpp | 46 ++---- src/karts/kart_with_stats.hpp | 3 +- src/karts/rescue_animation.cpp | 99 ++++++++++++ src/karts/rescue_animation.hpp | 61 ++++++++ src/modes/linear_world.cpp | 4 +- src/modes/three_strikes_battle.cpp | 3 +- src/modes/world.cpp | 5 +- src/modes/world.hpp | 3 +- src/network/race_state.cpp | 8 +- src/physics/physics.cpp | 15 +- src/states_screens/race_gui_base.cpp | 32 ++-- src/tracks/check_canon.cpp | 3 +- src/tracks/check_structure.cpp | 1 + 35 files changed, 868 insertions(+), 274 deletions(-) create mode 100644 src/karts/abstract_kart_animation.cpp create mode 100644 src/karts/abstract_kart_animation.hpp create mode 100644 src/karts/canon_animation.cpp create mode 100644 src/karts/canon_animation.hpp create mode 100644 src/karts/explosion_animation.cpp create mode 100644 src/karts/explosion_animation.hpp create mode 100644 src/karts/rescue_animation.cpp create mode 100644 src/karts/rescue_animation.hpp diff --git a/src/graphics/camera.cpp b/src/graphics/camera.cpp index 82e95228f..0622b6c27 100644 --- a/src/graphics/camera.cpp +++ b/src/graphics/camera.cpp @@ -30,6 +30,7 @@ #include "graphics/irr_driver.hpp" #include "io/xml_node.hpp" #include "karts/abstract_kart.hpp" +#include "karts/explosion_animation.hpp" #include "karts/kart_properties.hpp" #include "karts/skidding.hpp" #include "modes/world.hpp" @@ -445,7 +446,7 @@ void Camera::update(float dt) // If an explosion is happening, stop moving the camera, // but keep it target on the kart. - if(m_kart->playingExplosionAnimation()) + if(dynamic_cast(m_kart->getKartAnimation())) { // The camera target needs to be 'smooth moved', otherwise // there will be a noticable jump in the first frame diff --git a/src/graphics/slip_stream.cpp b/src/graphics/slip_stream.cpp index 29aed8752..2895e4726 100644 --- a/src/graphics/slip_stream.cpp +++ b/src/graphics/slip_stream.cpp @@ -389,9 +389,9 @@ void SlipStream::update(float dt) m_target_kart= world->getKart(i); // Don't test for slipstream with itself, a kart that is being // rescued or exploding, or an eliminated kart - if(m_target_kart==m_kart || - m_target_kart->playingEmergencyAnimation() || - m_target_kart->isEliminated() ) continue; + if(m_target_kart==m_kart || + m_target_kart->getKartAnimation() || + m_target_kart->isEliminated() ) continue; float diff = fabsf(m_target_kart->getXYZ().getY() - m_kart->getXYZ().getY() ); diff --git a/src/ide/vc9/supertuxkart.vcproj b/src/ide/vc9/supertuxkart.vcproj index 590c954ff..942a27d7e 100644 --- a/src/ide/vc9/supertuxkart.vcproj +++ b/src/ide/vc9/supertuxkart.vcproj @@ -832,6 +832,18 @@ RelativePath="..\..\karts\abstract_kart.cpp" > + + + + + + @@ -840,10 +852,6 @@ RelativePath="..\..\karts\kart.cpp" > - - @@ -872,6 +880,10 @@ RelativePath="..\..\karts\moveable.cpp" > + + @@ -1986,6 +1998,18 @@ RelativePath="..\..\karts\abstract_kart.hpp" > + + + + + + @@ -1994,10 +2018,6 @@ RelativePath="..\..\karts\kart.hpp" > - - @@ -2026,6 +2046,10 @@ RelativePath="..\..\karts\moveable.hpp" > + + diff --git a/src/items/attachment.cpp b/src/items/attachment.cpp index ac584ce91..417429a3a 100644 --- a/src/items/attachment.cpp +++ b/src/items/attachment.cpp @@ -29,6 +29,7 @@ #include "items/swatter.hpp" #include "karts/abstract_kart.hpp" #include "karts/controller/controller.hpp" +#include "karts/explosion_animation.hpp" #include "karts/kart_properties.hpp" #include "modes/three_strikes_battle.hpp" #include "network/race_state.hpp" @@ -208,7 +209,7 @@ void Attachment::hitBanana(Item *item, int new_attachment) if (dynamic_cast(World::getWorld()) != NULL) { World::getWorld()->kartHit(m_kart->getWorldKartId()); - m_kart->explode(Vec3(0.0f, 1.0f, 0.0f), true); + ExplosionAnimation::create(m_kart); return; } @@ -221,8 +222,7 @@ void Attachment::hitBanana(Item *item, int new_attachment) if(m_kart->getController()->isPlayerController()) he->setPlayerKartHit(); projectile_manager->addHitEffect(he); - - m_kart->explode(m_kart->getXYZ(), /*direct_hit*/ true); + ExplosionAnimation::create(m_kart); clear(); if(new_attachment==-1) new_attachment = m_random.get(3); @@ -395,8 +395,7 @@ void Attachment::update(float dt) if(m_kart->getController()->isPlayerController()) he->setPlayerKartHit(); projectile_manager->addHitEffect(he); - m_kart->explode(m_kart->getXYZ(), - /*direct_hit*/ true); + ExplosionAnimation::create(m_kart); if (m_bomb_sound) { diff --git a/src/items/flyable.cpp b/src/items/flyable.cpp index 87b2c1bce..510b2c6e7 100644 --- a/src/items/flyable.cpp +++ b/src/items/flyable.cpp @@ -36,6 +36,7 @@ #include "io/xml_node.hpp" #include "items/projectile_manager.hpp" #include "karts/abstract_kart.hpp" +#include "karts/explosion_animation.hpp" #include "modes/world.hpp" #include "network/flyable_info.hpp" #include "tracks/track.hpp" @@ -216,7 +217,7 @@ void Flyable::getClosestKart(const AbstractKart **minKart, // it is not considered a target anymore. if(kart->isEliminated() || kart == m_owner || kart->isInvulnerable() || - kart->playingEmergencyAnimation() ) continue; + kart->getKartAnimation() ) continue; btTransform t=kart->getTrans(); Vec3 delta = t.getOrigin()-trans_projectile.getOrigin(); @@ -476,8 +477,9 @@ void Flyable::explode(AbstractKart *kart_hit, PhysicalObject *object) // rockets on short distance. if(m_owner!=kart || m_owner==kart_hit) { - // Set a flag it if was a direct hit. - kart->explode(getXYZ(), kart==kart_hit); + // The explosion animation will register itself with the kart + // and will free it later. + ExplosionAnimation::create(kart, getXYZ(), kart==kart_hit); if(kart==kart_hit && world->getTrack()->isArena()) { world->kartHit(kart->getWorldKartId()); diff --git a/src/items/swatter.cpp b/src/items/swatter.cpp index b48936cff..976fc4fbb 100644 --- a/src/items/swatter.cpp +++ b/src/items/swatter.cpp @@ -34,6 +34,7 @@ #include "items/attachment.hpp" #include "items/projectile_manager.hpp" #include "karts/controller/controller.hpp" +#include "karts/explosion_animation.hpp" #include "karts/kart_properties.hpp" #include "modes/world.hpp" #include "karts/abstract_kart.hpp" @@ -301,7 +302,7 @@ void Swatter::squashThingsAround() if(m_kart->getController()->isPlayerController()) he->setPlayerKartHit(); projectile_manager->addHitEffect(he); - m_kart->explode(m_kart->getXYZ(), /*direct_hit*/ true); + ExplosionAnimation::create(kart); } // if kart has bomb attached World::getWorld()->kartHit(kart->getWorldKartId()); } // for i < num_kartrs diff --git a/src/karts/abstract_kart.cpp b/src/karts/abstract_kart.cpp index 8a83d48e8..ad6dae9dc 100644 --- a/src/karts/abstract_kart.cpp +++ b/src/karts/abstract_kart.cpp @@ -20,6 +20,7 @@ #include "karts/abstract_kart.hpp" #include "items/powerup.hpp" +#include "karts/abstract_kart_animation.hpp" #include "karts/kart_model.hpp" #include "karts/kart_properties.hpp" #include "karts/kart_properties_manager.hpp" @@ -37,6 +38,7 @@ AbstractKart::AbstractKart(const std::string& ident, { m_world_kart_id = world_kart_id; m_kart_properties = kart_properties_manager->getKart(ident); + m_kart_animation = NULL; assert(m_kart_properties != NULL); // We have to take a copy of the kart model, since otherwise @@ -56,11 +58,19 @@ AbstractKart::AbstractKart(const std::string& ident, AbstractKart::~AbstractKart() { delete m_kart_model; + if(m_kart_animation) + delete m_kart_animation; } // ~AbstractKart // ---------------------------------------------------------------------------- void AbstractKart::reset() { + Moveable::reset(); + if(m_kart_animation) + { + delete m_kart_animation; + m_kart_animation = NULL; + } } // reset // ---------------------------------------------------------------------------- @@ -82,3 +92,29 @@ bool AbstractKart::isWheeless() const return m_kart_model->getWheelModel(0)==NULL; } // isWheeless +// ---------------------------------------------------------------------------- +/** Sets a new kart animation. This function should either be called to + * remove an existing kart animation (ka=NULL), or to set a new kart + * animation, in which case the current kart animation must be NULL. + * \param ka The new kart animation, or NULL if the current kart animation + * is to be stopped. + */ +void AbstractKart::setKartAnimation(AbstractKartAnimation *ka) +{ +#ifdef DEBUG + if( ( (ka!=NULL) ^ (m_kart_animation!=NULL) ) ==0) + { + if(ka) printf("Setting kart animation to '%s'.\n", + ka->getName().c_str()); + else printf("Setting kart animation to NULL.\n"); + if(m_kart_animation) printf("Current kart animation is '%s'.\n", + m_kart_animation->getName().c_str()); + else printf("Current kart animation is NULL.\n"); + } +#endif + // Make sure that the either the current animation is NULL and a new (!=0) + // is set, or there is a current animation, then it must be set to 0. This + // makes sure that the calling logic of this function is correct. + assert( (ka!=NULL) ^ (m_kart_animation!=NULL) ); + m_kart_animation = ka; +} // setKartAnimation diff --git a/src/karts/abstract_kart.hpp b/src/karts/abstract_kart.hpp index c87344506..eda869495 100644 --- a/src/karts/abstract_kart.hpp +++ b/src/karts/abstract_kart.hpp @@ -31,6 +31,7 @@ class btUprightConstraint; class Camera; class Controller; class Item; +class AbstractKartAnimation; class KartModel; class KartProperties; class Material; @@ -71,6 +72,9 @@ protected: /** The kart controls (e.g. steering, fire, ...). */ KartControl m_controls; + /** A kart animation object to handle rescue, explosion etc. */ + AbstractKartAnimation *m_kart_animation; + public: AbstractKart(const std::string& ident, int world_kart_id, @@ -146,23 +150,16 @@ public: // ======================================================================== // Emergency animation related functions. // ------------------------------------------------------------------------ - /** Returns true if an emergency animation is being played. */ - virtual bool playingEmergencyAnimation() const = 0; + /** Returns a kart animation (if any), or NULL if currently no kart + * animation is being shown. */ + AbstractKartAnimation *getKartAnimation() { return m_kart_animation; } // ------------------------------------------------------------------------ - /** Returns true if an emergency animation is being played. */ - virtual bool playingExplosionAnimation() const = 0; + const AbstractKartAnimation *getKartAnimation() const + { return m_kart_animation; } // ------------------------------------------------------------------------ - /** Returns true if an emergency animation is being played. */ - virtual bool playingRescueAnimation() const = 0; + /** Sets a new kart animation. */ + void setKartAnimation(AbstractKartAnimation *ka); // ------------------------------------------------------------------------ - virtual void explode(const Vec3& pos, bool direct_hit) = 0; - // ------------------------------------------------------------------------ - virtual void rescue(bool is_auto_rescue=false) = 0; - // ------------------------------------------------------------------------ - virtual void shootTo(const Vec3 &target, float speed) = 0; - // ------------------------------------------------------------------------ - /** Returns the timer for the currently played animation. */ - virtual float getAnimationTimer() const = 0; // ------------------------------------------------------------------------ // ------------------------------------------------------------------------ @@ -189,7 +186,7 @@ public: virtual bool isEliminated() const = 0; // ------------------------------------------------------------------------ /** Marks this kart to be eliminated. */ - virtual void eliminate (bool remove) = 0; + virtual void eliminate() = 0; // ------------------------------------------------------------------------ virtual void finishedRace(float time) = 0; // ------------------------------------------------------------------------ @@ -365,6 +362,11 @@ public: /** Returns if the kart is invulnerable. */ virtual bool isInvulnerable() const = 0; // ------------------------------------------------------------------------ + virtual void setInvulnerableTime(float t) = 0; + // ------------------------------------------------------------------------ + /** Shows the star effect for a certain time. */ + virtual void showStarEffect(float t) = 0; + // ------------------------------------------------------------------------ /** Called when the kart crashes against another kart. * \param k The kart that was hit. * \param update_attachments If true the attachment of this kart and the diff --git a/src/karts/abstract_kart_animation.cpp b/src/karts/abstract_kart_animation.cpp new file mode 100644 index 000000000..2ff34aa6c --- /dev/null +++ b/src/karts/abstract_kart_animation.cpp @@ -0,0 +1,48 @@ +// +// 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/abstract_kart.hpp" +#include "karts/abstract_kart_animation.hpp" + +AbstractKartAnimation::AbstractKartAnimation(AbstractKart *kart) +{ + m_timer = 0; + m_kart = kart; + // Register this animation with the kart (which will free it + // later). + kart->setKartAnimation(this); +} // AbstractKartAnimation + +// ---------------------------------------------------------------------------- +/** Updates the timer, and if it expires (<0), the kart animation will be + * removed from the kart and this object will be deleted. + * NOTE: calling this function must be the last thing done in any kart + * animation class, since this object might be deleted, so accessing any + * members might be invalid. + * \param dt Time step size. + */ +void AbstractKartAnimation::update(float dt) +{ + // See if the timer expires, if so return the kart to normal game play + m_timer -= dt; + if(m_timer<0) + { + m_kart->setKartAnimation(NULL); + delete this; + } +} // update diff --git a/src/karts/abstract_kart_animation.hpp b/src/karts/abstract_kart_animation.hpp new file mode 100644 index 000000000..a073f9267 --- /dev/null +++ b/src/karts/abstract_kart_animation.hpp @@ -0,0 +1,61 @@ +// +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2012 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_ABSTRACT_KART_ANIMATION_HPP +#define HEADER_ABSTRACT_KART_ANIMATION_HPP + +#include "utils/no_copy.hpp" +#include "utils/vec3.hpp" + +#include + +class AbstractKart; + +/** The base class for all kart animation, like rescue, explosion, or canon. + * Kart animations are done by removing the physics body from the physics + * world, and instead modifying the rotation and position of the kart + * directly. They are registered with the kart, and only one can be + * used at the same time. The memory is handled by the kart object, so + * there is no need to manage it. Sample usage: + * new ExplosionAnimation(kart); + * The object does not need to be stored. + */ +class AbstractKartAnimation: public NoCopy +{ +protected: + /** A pointer to the kart which is animated by this class. */ + AbstractKart *m_kart; + + /** Timer for the explosion. */ + float m_timer; + +public: + AbstractKartAnimation(AbstractKart *kart); + virtual ~AbstractKartAnimation() {} + virtual void update(float dt); + // ------------------------------------------------------------------------ + virtual float getAnimationTimer() const { return m_timer; } +#ifdef DEBUG + /** To easily allow printing the name of the animation being used atm. + * Used in AstractKart in case of an incorrect sequence of calls. */ + virtual const std::string getName() const = 0; +#endif + +}; // AbstractKartAnimation + +#endif diff --git a/src/karts/canon_animation.cpp b/src/karts/canon_animation.cpp new file mode 100644 index 000000000..6576df47b --- /dev/null +++ b/src/karts/canon_animation.cpp @@ -0,0 +1,72 @@ +// +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2012 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/canon_animation.hpp" + +#include "karts/abstract_kart.hpp" +#include "modes/world.hpp" + +#include "LinearMath/btTransform.h" + +CanonAnimation::CanonAnimation(AbstractKart *kart, const Vec3 &target, + float speed) + : AbstractKartAnimation(kart) +{ + m_xyz = m_kart->getXYZ(); + assert(speed>0); + Vec3 delta = target-m_kart->getXYZ(); + m_timer = delta.length()/speed; + m_velocity = delta/m_timer; + + World::getWorld()->getPhysics()->removeKart(m_kart); + + m_curr_rotation.setHeading(m_kart->getHeading()); + m_curr_rotation.setPitch(m_kart->getPitch()); + m_curr_rotation.setRoll(m_kart->getRoll()); + + m_add_rotation.setHeading(0); + m_add_rotation.setPitch( 0); + m_add_rotation.setRoll( 0); +} // CanonAnimation + +// ---------------------------------------------------------------------------- +CanonAnimation::~CanonAnimation() +{ + btTransform trans = m_kart->getTrans(); + trans.setOrigin(m_xyz); + m_kart->setTrans(trans); + m_kart->getBody()->setCenterOfMassTransform(trans); + World::getWorld()->getPhysics()->addKart(m_kart); +} // ~CanonAnimation + +// ---------------------------------------------------------------------------- +/** Updates the kart animation. + * \param dt Time step size. + * \return True if the explosion is still shown, false if it has finished. + */ +void CanonAnimation::update(float dt) +{ + m_xyz += dt*m_velocity; + 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); + + AbstractKartAnimation::update(dt); +} // update diff --git a/src/karts/canon_animation.hpp b/src/karts/canon_animation.hpp new file mode 100644 index 000000000..19a66f706 --- /dev/null +++ b/src/karts/canon_animation.hpp @@ -0,0 +1,61 @@ +// +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2012 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_CANON_ANIMATION_HPP +#define HEADER_CANON_ANIMATION_HPP + +#include "karts/abstract_kart_animation.hpp" +#include "utils/vec3.hpp" + +/** This animation shoots the kart to a specified point on the track. + * + * \ingroup karts + */ + +class AbstractKart; + +class CanonAnimation: public AbstractKartAnimation +{ +protected: + /** The coordinates where the kart was hit originally. */ + Vec3 m_xyz; + + /** The kart's current rotation. */ + Vec3 m_curr_rotation; + + /** The artificial rotation to toss the kart around. It's in units + * of rotation per second. */ + Vec3 m_add_rotation; + + /** The velocity with which the kart is moved. */ + Vec3 m_velocity; + + /** 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; + +public: + CanonAnimation(AbstractKart *kart, const Vec3 &target, + float speed); + virtual ~CanonAnimation(); + virtual void update(float dt); + virtual const std::string getName() const {return "Canon";} + +}; // CanonAnimation +#endif diff --git a/src/karts/controller/default_ai_controller.cpp b/src/karts/controller/default_ai_controller.cpp index b5a03337b..775c9359e 100644 --- a/src/karts/controller/default_ai_controller.cpp +++ b/src/karts/controller/default_ai_controller.cpp @@ -43,6 +43,7 @@ #include "karts/controller/kart_control.hpp" #include "karts/kart_properties.hpp" #include "karts/max_speed.hpp" +#include "karts/rescue_animation.hpp" #include "items/attachment.hpp" #include "items/powerup.hpp" #include "modes/linear_world.hpp" @@ -194,7 +195,7 @@ void DefaultAIController::update(float dt) // If the kart needs to be rescued, do it now (and nothing else) if(isStuck()) { - m_kart->rescue(); + new RescueAnimation(m_kart); AIBaseController::update(dt); return; } @@ -458,7 +459,7 @@ void DefaultAIController::handleSteering(float dt) void DefaultAIController::handleItems(const float dt) { m_controls->m_fire = false; - if(m_kart->playingEmergencyAnimation() || + if(m_kart->getKartAnimation() || m_kart->getPowerup()->getType() == PowerupManager::POWERUP_NOTHING ) return; @@ -743,13 +744,13 @@ void DefaultAIController::handleRaceStart() void DefaultAIController::handleRescue(const float dt) { // check if kart is stuck - if(m_kart->getSpeed()<2.0f && !m_kart->playingEmergencyAnimation() && + if(m_kart->getSpeed()<2.0f && !m_kart->getKartAnimation() && !m_world->isStartPhase()) { m_time_since_stuck += dt; if(m_time_since_stuck > 2.0f) { - m_kart->rescue(); + new RescueAnimation(m_kart); m_time_since_stuck=0.0f; } // m_time_since_stuck > 2.0f } diff --git a/src/karts/controller/end_controller.cpp b/src/karts/controller/end_controller.cpp index 1e133badf..0d55354bb 100644 --- a/src/karts/controller/end_controller.cpp +++ b/src/karts/controller/end_controller.cpp @@ -41,6 +41,7 @@ #include "karts/abstract_kart.hpp" #include "karts/max_speed.hpp" +#include "karts/rescue_animation.hpp" #include "modes/linear_world.hpp" #include "network/network_manager.hpp" #include "race/race_manager.hpp" @@ -226,13 +227,13 @@ void EndController::handleSteering(float dt) void EndController::handleRescue(const float DELTA) { // check if kart is stuck - if(m_kart->getSpeed()<2.0f && !m_kart->playingEmergencyAnimation() && + if(m_kart->getSpeed()<2.0f && !m_kart->getKartAnimation() && !m_world->isStartPhase()) { m_time_since_stuck += DELTA; if(m_time_since_stuck > 2.0f) { - m_kart->rescue(); + new RescueAnimation(m_kart); m_time_since_stuck=0.0f; } // m_time_since_stuck > 2.0f } diff --git a/src/karts/controller/new_ai_controller.cpp b/src/karts/controller/new_ai_controller.cpp index e26acca29..6c1bb7a1e 100644 --- a/src/karts/controller/new_ai_controller.cpp +++ b/src/karts/controller/new_ai_controller.cpp @@ -43,6 +43,7 @@ #include "items/powerup.hpp" #include "karts/abstract_kart.hpp" #include "karts/controller/kart_control.hpp" +#include "karts/rescue_animation.hpp" #include "karts/max_speed.hpp" #include "modes/linear_world.hpp" #include "network/network_manager.hpp" @@ -357,7 +358,7 @@ void NewAIController::handleSteering(float dt) void NewAIController::handleItems( const float DELTA, const int STEPS ) { m_controls->m_fire = false; - if(m_kart->playingEmergencyAnimation() || + if(m_kart->getKartAnimation() || m_kart->getPowerup()->getType() == PowerupManager::POWERUP_NOTHING ) return; @@ -571,13 +572,13 @@ void NewAIController::handleRaceStart() void NewAIController::handleRescue(const float DELTA) { // check if kart is stuck - if(m_kart->getSpeed()<2.0f && !m_kart->playingEmergencyAnimation() && + if(m_kart->getSpeed()<2.0f && !m_kart->getKartAnimation() && !m_world->isStartPhase()) { m_time_since_stuck += DELTA; if(m_time_since_stuck > 2.0f) { - m_kart->rescue(); + new RescueAnimation(m_kart); m_time_since_stuck=0.0f; } // m_time_since_stuck > 2.0f } diff --git a/src/karts/controller/player_controller.cpp b/src/karts/controller/player_controller.cpp index de2bd28fc..96abedb46 100644 --- a/src/karts/controller/player_controller.cpp +++ b/src/karts/controller/player_controller.cpp @@ -29,6 +29,7 @@ #include "items/item.hpp" #include "items/powerup.hpp" #include "karts/abstract_kart.hpp" +#include "karts/rescue_animation.hpp" #include "modes/world.hpp" #include "race/history.hpp" #include "states_screens/race_gui_base.hpp" @@ -338,7 +339,7 @@ void PlayerController::update(float dt) return; } - if ( m_controls->m_fire && !m_kart->playingEmergencyAnimation()) + if ( m_controls->m_fire && !m_kart->getKartAnimation()) { if (m_kart->getPowerup()->getType()==PowerupManager::POWERUP_NOTHING) m_kart->beep(); @@ -365,10 +366,10 @@ void PlayerController::update(float dt) // up sitting on a brick wall, with all wheels in the air :(( if ( m_controls->m_rescue ) { - m_kart->rescue(); + new RescueAnimation(m_kart); m_controls->m_rescue=false; } - if (m_kart->playingEmergencyAnimation() && + if (m_kart->getKartAnimation() && m_kart->getAttachment()->getType() != Attachment::ATTACH_TINYTUX) { m_bzzt_sound->play(); diff --git a/src/karts/explosion_animation.cpp b/src/karts/explosion_animation.cpp new file mode 100644 index 000000000..ac27bdd35 --- /dev/null +++ b/src/karts/explosion_animation.cpp @@ -0,0 +1,135 @@ +// +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2012 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 "audio/sfx_manager.hpp" +#include "items/attachment.hpp" +#include "karts/abstract_kart.hpp" +#include "karts/kart_properties.hpp" +#include "modes/world.hpp" +#include "tracks/track.hpp" + +/** A static create function that does only create an explosion if + * the explosion happens to be close enough to affect the kart. + * Otherwise, NULL is returned. + * \param kart The kart that is exploded. + * \param pos The position where the explosion happened. + * \param direct_hit If the kart was hit directly. + */ +ExplosionAnimation *ExplosionAnimation::create(AbstractKart *kart, + const Vec3 &pos, + bool direct_hit) +{ + if(kart->isInvulnerable()) return NULL; + + float r = kart->getKartProperties()->getExplosionRadius(); + if(!direct_hit && pos.distance2(kart->getXYZ())>r*r) return NULL; + + return new ExplosionAnimation(kart, pos, direct_hit); +} // create + +// ---------------------------------------------------------------------------- +/** A static create function that does only create an explosion if + * the explosion happens to be close enough to affect the kart. + * Otherwise, NULL is returned. */ +ExplosionAnimation *ExplosionAnimation::create(AbstractKart *kart) +{ + if(kart->isInvulnerable()) return NULL; + return new ExplosionAnimation(kart, kart->getXYZ(), /*direct hit*/true); +} // create + +// ---------------------------------------------------------------------------- +ExplosionAnimation::ExplosionAnimation(AbstractKart *kart, + const Vec3 &explosion_position, + bool direct_hit) + : AbstractKartAnimation(kart) + { + m_xyz = m_kart->getXYZ(); + // Ignore explosion that are too far away. + + m_kart->playCustomSFX(SFXManager::CUSTOM_EXPLODE); + m_timer = m_kart->getKartProperties()->getExplosionTime();; + + // Non-direct hits will be only affected half as much. + if(!direct_hit) m_timer*=0.5f; + + // 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_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_velocity = 0.5f * m_timer * World::getWorld()->getTrack()->getGravity(); + World::getWorld()->getPhysics()->removeKart(m_kart); + + m_curr_rotation.setHeading(m_kart->getHeading()); + m_curr_rotation.setPitch(m_kart->getPitch()); + m_curr_rotation.setRoll(m_kart->getRoll()); + + const int max_rotation = direct_hit ? 2 : 1; + // To get rotations in both directions for each axis we determine a random + // number between -(max_rotation-1) and +(max_rotation-1) + float f=2.0f*M_PI/m_timer; + 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 ); + + // Set invulnerable time, and graphical effects + float t = m_kart->getKartProperties()->getExplosionInvulnerabilityTime(); + m_kart->setInvulnerableTime(t); + if ( UserConfigParams::m_graphical_effects ) + { + m_kart->showStarEffect(t); + } + + m_kart->getAttachment()->clear(); + + }; // ExplosionAnimation + +//----------------------------------------------------------------------------- +ExplosionAnimation::~ExplosionAnimation() +{ + m_kart->getBody()->setLinearVelocity(btVector3(0,0,0)); + m_kart->getBody()->setAngularVelocity(btVector3(0,0,0)); + World::getWorld()->getPhysics()->addKart(m_kart); + if(m_kart->getCamera() && + m_kart->getCamera()->getMode() != Camera::CM_FINAL) + m_kart->getCamera()->setMode(Camera::CM_NORMAL); + return; +} // ~KartAnimation + +// ---------------------------------------------------------------------------- +/** Updates the kart animation. + * \param dt Time step size. + * \return True if the explosion is still shown, false if it has finished. + */ +void ExplosionAnimation::update(float dt) +{ + m_velocity -= dt*World::getWorld()->getTrack()->getGravity(); + + m_xyz.setY(m_xyz.getY() + dt*m_velocity); + 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); + + AbstractKartAnimation::update(dt); +} // update diff --git a/src/karts/explosion_animation.hpp b/src/karts/explosion_animation.hpp new file mode 100644 index 000000000..4cc579f3c --- /dev/null +++ b/src/karts/explosion_animation.hpp @@ -0,0 +1,70 @@ +// +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2012 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 "karts/abstract_kart_animation.hpp" +#include "utils/vec3.hpp" + +/** + * \brief 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. + * \ingroup karts + */ +class ExplosionAnimation: public AbstractKartAnimation +{ +protected: + /** The coordinates where the kart was hit originally. */ + Vec3 m_xyz; + + /** The kart's current rotation. */ + Vec3 m_curr_rotation; + + /** The artificial rotation to toss the kart around. It's in units + * of rotation per second. */ + Vec3 m_add_rotation; + + /** The velocity with which the kart is moved. */ + float m_velocity; + + /** 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; + + ExplosionAnimation(AbstractKart *kart); + ExplosionAnimation(AbstractKart *kart, const Vec3 &pos, + bool direct_hit); +public: + static ExplosionAnimation *create(AbstractKart *kart, const Vec3 &pos, + bool direct_hit); + static ExplosionAnimation *create(AbstractKart *kart); + + virtual ~ExplosionAnimation(); + virtual void update(float dt); + virtual const std::string getName() const { return "Explosion"; } +}; // ExplosionAnimation +#endif diff --git a/src/karts/kart.cpp b/src/karts/kart.cpp index 8b9763ee2..b66802de0 100644 --- a/src/karts/kart.cpp +++ b/src/karts/kart.cpp @@ -39,13 +39,16 @@ #include "graphics/shadow.hpp" #include "graphics/skid_marks.hpp" #include "graphics/slip_stream.hpp" +#include "graphics/stars.hpp" +#include "karts/explosion_animation.hpp" #include "karts/kart_gfx.hpp" +#include "karts/rescue_animation.hpp" #include "modes/world.hpp" #include "io/file_manager.hpp" #include "items/attachment.hpp" #include "items/item_manager.hpp" #include "karts/controller/end_controller.hpp" -#include "karts/kart_animation.hpp" +#include "karts/abstract_kart_animation.hpp" #include "karts/kart_model.hpp" #include "karts/kart_properties_manager.hpp" #include "karts/max_speed.hpp" @@ -82,7 +85,6 @@ Kart::Kart (const std::string& ident, unsigned int world_kart_id, # pragma warning(1:4355) #endif { - m_kart_animation = new KartAnimation(this); m_max_speed = new MaxSpeed(this); m_terrain_info = new TerrainInfo(); m_powerup = new Powerup(this); @@ -140,6 +142,14 @@ Kart::Kart (const std::string& ident, unsigned int world_kart_id, m_terrain_sound = NULL; m_previous_terrain_sound = NULL; + // Create the stars effect + m_stars_effect = + new Stars(getNode(), + core::vector3df(0.0f, + getKartModel()->getModel() + ->getBoundingBox().MaxEdge.Y, + 0.0f) ); + } // Kart // ----------------------------------------------------------------------------- @@ -242,7 +252,6 @@ Kart::~Kart() } delete m_skidding; delete m_max_speed; - delete m_kart_animation; delete m_terrain_info; delete m_powerup; @@ -264,8 +273,9 @@ void Kart::reset() m_flying = false; stopFlying(); } - - m_kart_animation->reset(); + + // Reset star effect in case that it is currently being shown. + m_stars_effect->reset(); m_max_speed->reset(); m_powerup->reset(); @@ -297,6 +307,7 @@ void Kart::reset() m_race_position = m_initial_position; m_finished_race = false; + m_eliminated = false; m_finish_time = 0.0f; m_bubblegum_time = 0.0f; m_invulnerable_time = 0.0f; @@ -342,7 +353,7 @@ void Kart::reset() applyEngineForce (0.0f); - Moveable::reset(); + AbstractKart::reset(); if (m_skidmarks) { m_skidmarks->reset(); @@ -392,31 +403,6 @@ float Kart::getSpeedIncreaseTimeLeft(unsigned int category) const { return m_max_speed->getSpeedIncreaseTimeLeft(category); } // getSpeedIncreaseTimeLeft -// ----------------------------------------------------------------------------- -bool Kart::playingRescueAnimation() const -{ - return m_kart_animation->playingRescueAnimation(); -} // playingRescueAnimation - -// ----------------------------------------------------------------------------- -bool Kart::playingExplosionAnimation() const -{ - return m_kart_animation->playingExplosionAnimation(); -} // playingExplosionAnimation - -// ----------------------------------------------------------------------------- -/** Returns the timer for the currently played animation. */ -float Kart::getAnimationTimer() const -{ - return m_kart_animation->getAnimationTimer(); -} // getAnimationTimer - -// ----------------------------------------------------------------------------- -/** Returns true if an emergency animation is being played. */ -bool Kart::playingEmergencyAnimation() const -{ - return m_kart_animation->playingAnimation(); -} // playingEmergencyAnimation // ----------------------------------------------------------------------------- /** Returns the current material the kart is on. */ @@ -881,7 +867,7 @@ float Kart::getActualWheelForce() bool Kart::isOnGround() const { return ((int)m_vehicle->getNumWheelsOnGround() == m_vehicle->getNumWheels() - && !playingEmergencyAnimation()); + && !getKartAnimation()); } // isOnGround //----------------------------------------------------------------------------- @@ -899,46 +885,31 @@ bool Kart::isNearGround() const } // isNearGround //----------------------------------------------------------------------------- -/** Returns true if the kart is eliminated. +/** Shows the star effect for a certain time. + * \param t Time to show the star effect for. */ -bool Kart::isEliminated() const +void Kart::showStarEffect(float t) { - return m_kart_animation->isEliminated(); -} // isEliminated -// ------------------------------------------------------------------------ -void Kart::eliminate(bool remove) + m_stars_effect->showFor(t); +} // showStarEffect + +//----------------------------------------------------------------------------- +void Kart::eliminate() { - m_kart_animation->eliminate(remove); + if (!getKartAnimation()) + { + World::getWorld()->getPhysics()->removeKart(this); + } + if (m_stars_effect) + { + m_stars_effect->reset(); + m_stars_effect->update(1); + } + + m_eliminated = true; + + m_node->setVisible(false); } // eliminate -// ------------------------------------------------------------------------ -/** Starts an explosion animation. - * \param pos The coordinates of the explosion. - * \param direct_hig True if the kart was hit directly --> maximal impact. - */ -void Kart::explode(const Vec3& pos, bool direct_hit) -{ - m_kart_animation->explode(pos, direct_hit); -} // explode - -//----------------------------------------------------------------------------- -/** Sets the mode of the kart to being rescued, attaches the rescue model - * and saves the current pitch and roll (for the rescue animation). It - * also removes the kart from the physics world. - */ -void Kart::rescue(bool is_auto_rescue) -{ - m_kart_animation->rescue(is_auto_rescue); -} // rescue - -//----------------------------------------------------------------------------- -/** Starts a 'shooting' animation to a specific point. - * \param target The coordinates to fly to - * \param speed The speed to use when flying. - */ -void Kart::shootTo(const Vec3 &target, float speed) -{ - m_kart_animation->shootTo(target, speed); -} // shootTo //----------------------------------------------------------------------------- /** Updates the kart in each time step. It updates the physics setting, @@ -947,7 +918,13 @@ void Kart::shootTo(const Vec3 &target, float speed) */ void Kart::update(float dt) { - if (m_kart_animation->isEliminated()) + if ( UserConfigParams::m_graphical_effects ) + { + // update star effect (call will do nothing if stars are not activated) + m_stars_effect->update(dt); + } + + if (isEliminated()) { m_kart_animation->update(dt); return; @@ -1002,7 +979,7 @@ void Kart::update(float dt) // On a client fiering is done upon receiving the command from the server. if ( m_controls.m_fire && network_manager->getMode()!=NetworkManager::NW_CLIENT - && !playingEmergencyAnimation()) + && !getKartAnimation()) { // use() needs to be called even if there currently is no collecteable // since use() can test if something needs to be switched on/off. @@ -1044,7 +1021,8 @@ void Kart::update(float dt) m_wheel_rotation += m_speed*dt / m_kart_properties->getWheelRadius(); m_wheel_rotation=fmodf(m_wheel_rotation, 2*M_PI); - m_kart_animation->update(dt); + if(m_kart_animation) + m_kart_animation->update(dt); m_attachment->update(dt); @@ -1076,9 +1054,10 @@ void Kart::update(float dt) m_skid_sound->position ( getXYZ() ); // Check if a kart is (nearly) upside down and not moving much --> automatic rescue - if((fabs(getRoll())>60*DEGREE_TO_RAD && fabs(getSpeed())<3.0f) ) + if(!getKartAnimation() && fabs(getRoll())>60*DEGREE_TO_RAD && + fabs(getSpeed())<3.0f ) { - rescue(/*is_auto_rescue*/true); + new RescueAnimation(this, /*is_auto_rescue*/true); } btTransform trans=getTrans(); @@ -1112,13 +1091,13 @@ void Kart::update(float dt) const Vec3 *min, *max; World::getWorld()->getTrack()->getAABB(&min, &max); if(min->getY() - getXYZ().getY() > 17 && !m_flying) - rescue(); + new RescueAnimation(this); } else { handleMaterialSFX(material); if (material->isDriveReset() && isOnGround()) - rescue(); + new RescueAnimation(this); else if(material->isZipper() && isOnGround()) { handleZipper(material); @@ -1154,7 +1133,7 @@ void Kart::update(float dt) (m_bubblegum_time > 0 ? &pink : NULL) ); } - const bool emergency = playingEmergencyAnimation(); + const bool emergency = getKartAnimation()!=NULL; if (emergency) { @@ -1202,7 +1181,7 @@ void Kart::setSquash(float time, float slowdown) if(m_attachment->getType()==Attachment::ATTACH_BOMB) { - explode(getXYZ(), /*direct hit*/true); + ExplosionAnimation::create(this); return; } m_node->setScale(core::vector3df(1.0f, 0.5f, 1.0f)); @@ -1296,7 +1275,7 @@ void Kart::handleMaterialGFX() // something with the wheels, and the material has not the // below surface property set. if (material && isOnGround() && !material->isBelowSurface() && - !m_kart_animation->playingRescueAnimation()&& + !dynamic_cast(getKartAnimation()) && UserConfigParams::m_graphical_effects) { @@ -1353,7 +1332,7 @@ void Kart::handleMaterialGFX() const ParticleKind *pk = surface_material->getParticlesWhen(Material::EMIT_ON_DRIVE); - if(!pk || m_flying || m_kart_animation->playingRescueAnimation()) + if(!pk || m_flying || dynamic_cast(getKartAnimation())) return; // Now the kart is under a surface, and there is a surface effect @@ -1371,7 +1350,7 @@ void Kart::handleMaterialGFX() // Play special sound effects for this terrain // ------------------------------------------- const std::string s = surface_material->getSFXName(); - if (s != "" && !m_kart_animation->playingRescueAnimation()&& + if (s != "" && !dynamic_cast(getKartAnimation())&& (m_terrain_sound == NULL || m_terrain_sound->getStatus() == SFXManager::SFX_STOPPED)) { if (m_previous_terrain_sound) sfx_manager->deleteSFX(m_previous_terrain_sound); @@ -1566,7 +1545,7 @@ void Kart::crashed(const Material *m) * for 0.5 seconds after a crash. */ if(m && m->getCollisionReaction() != Material::NORMAL && - !playingEmergencyAnimation()) + !getKartAnimation()) { std::string particles = m->getCrashResetParticles(); if (particles.size() > 0) @@ -1596,7 +1575,7 @@ void Kart::crashed(const Material *m) if (m->getCollisionReaction() == Material::RESCUE) { - rescue(); + new RescueAnimation(this); } else if (m->getCollisionReaction() == Material::PUSH_BACK) { diff --git a/src/karts/kart.hpp b/src/karts/kart.hpp index 0963b5492..4f15d6074 100644 --- a/src/karts/kart.hpp +++ b/src/karts/kart.hpp @@ -41,7 +41,7 @@ class Attachment; class Camera; class Controller; class Item; -class KartAnimation; +class AbstractKartAnimation; class KartGFX; class MaxSpeed; class ParticleEmitter; @@ -52,6 +52,7 @@ class Shadow; class Skidding; class SkidMarks; class SlipStream; +class Stars; /** The main kart class. All type of karts are of this object, but with * different controllers. The controllers are what turn a kart into a @@ -65,10 +66,6 @@ class SlipStream; class Kart : public AbstractKart { friend class Skidding; -protected: - /** Handles all kart animations, such as rescue and explosion. */ - KartAnimation *m_kart_animation; - private: /** Handles speed increase and capping due to powerup, terrain, ... */ MaxSpeed *m_max_speed; @@ -104,7 +101,12 @@ private: /** Current race position (1-num_karts). */ int m_race_position; + /** True if the kart is eliminated. */ + bool m_eliminated; + /** For stars rotating around head effect */ + Stars *m_stars_effect; + protected: // Used by the AI atm /** The camera for each kart. Not all karts have cameras (e.g. AI karts @@ -254,9 +256,6 @@ public: virtual void setPosition(int p); virtual void beep (); virtual void showZipperFire (); - virtual bool playingExplosionAnimation() const; - virtual bool playingRescueAnimation() const; - virtual bool playingEmergencyAnimation() const; virtual float getCurrentMaxSpeed() const; virtual bool playCustomSFX (unsigned int type); @@ -380,21 +379,13 @@ public: * the upright constraint to allow for more realistic explosions. */ bool isNearGround () const; // ------------------------------------------------------------------------ - virtual bool isEliminated() const; + /** Returns true if the kart is eliminated. */ + virtual bool isEliminated() const { return m_eliminated; } // ------------------------------------------------------------------------ - virtual void eliminate (bool remove); - // ------------------------------------------------------------------------ - virtual void explode(const Vec3& pos, bool direct_hit); - // ------------------------------------------------------------------------ - virtual void rescue(bool is_auto_rescue=false); - // ------------------------------------------------------------------------ - virtual void shootTo(const Vec3 &target, float speed); - // ------------------------------------------------------------------------ - /** Returns the timer for the currently played animation. */ - virtual float getAnimationTimer() const; + virtual void eliminate(); // ------------------------------------------------------------------------ /** Makes a kart invulnerable for a certain amount of time. */ - void setInvulnerableTime(float t) { m_invulnerable_time = t; }; + virtual void setInvulnerableTime(float t) { m_invulnerable_time = t; }; // ------------------------------------------------------------------------ /** Returns if the kart is invulnerable. */ virtual bool isInvulnerable() const { return m_invulnerable_time > 0; } @@ -404,6 +395,9 @@ public: // ------------------------------------------------------------------------ /** Returns if the kart is currently being squashed. */ virtual bool isSquashed() const { return m_squash_time >0; } + // ------------------------------------------------------------------------ + /** Shows the star effect for a certain time. */ + virtual void showStarEffect(float t); }; // Kart diff --git a/src/karts/kart_animation.cpp b/src/karts/kart_animation.cpp index 90782fc25..9c088f74f 100644 --- a/src/karts/kart_animation.cpp +++ b/src/karts/kart_animation.cpp @@ -34,6 +34,7 @@ * \param kart Pointer to the kart which is animated. */ KartAnimation::KartAnimation(Kart *kart) + : I_KartAnimation(kart) { m_stars_effect = NULL; m_referee = NULL; @@ -44,7 +45,6 @@ KartAnimation::KartAnimation(Kart *kart) // reset() is also called at the very start, it must be guaranteed that // rescue is not set. m_kart_mode = KA_NONE; - m_eliminated = false; }; // KartAnimation //----------------------------------------------------------------------------- @@ -72,15 +72,11 @@ void KartAnimation::reset() // Reset star effect in case that it is currently being shown. m_stars_effect->reset(); - // If the kart was eliminated or rescued, the body was removed from the - // physics world. Add it again. - if(m_eliminated || playingAnimation()) - { - World::getWorld()->getPhysics()->addKart(m_kart); - } + // Note that this will only add the kart if it's not already + // in the world. + World::getWorld()->getPhysics()->addKart(m_kart); m_timer = 0; m_kart_mode = KA_NONE; - m_eliminated = false; if(m_referee) { delete m_referee; @@ -88,31 +84,6 @@ void KartAnimation::reset() } } // reset -//----------------------------------------------------------------------------- -/** Eliminates a kart from the race. It removes the kart from the physics - * world, and makes the scene node invisible. - */ -void KartAnimation::eliminate(bool remove) -{ - if (!playingAnimation() && remove) - { - World::getWorld()->getPhysics()->removeKart(m_kart); - } - - if (m_stars_effect) - { - m_stars_effect->reset(); - m_stars_effect->update(1); - } - - m_eliminated = true; - m_kart_mode = KA_NONE; - - if (remove) - { - m_kart->getNode()->setVisible(false); - } -} // eliminate //----------------------------------------------------------------------------- /** Sets the mode of the kart to being rescued, attaches the rescue model @@ -121,7 +92,7 @@ void KartAnimation::eliminate(bool remove) */ void KartAnimation::rescue(bool is_auto_rescue) { - if(playingAnimation()) return; + if(getKartAnimation()) return; assert(!m_referee); m_referee = new Referee(*m_kart); @@ -275,11 +246,6 @@ void KartAnimation::update(float dt) } World::getWorld()->getPhysics()->addKart(m_kart); m_kart_mode = KA_NONE; - // We have to make sure that m_kart_mode and m_eliminated are in - // synch, otherwise it can happen that a kart is entered in world - // here, and again in reset (e.g. when restarting the race) if - // m_eliminated is still true. - m_eliminated = false; if(m_kart->getCamera() && m_kart->getCamera()->getMode() != Camera::CM_FINAL) m_kart->getCamera()->setMode(Camera::CM_NORMAL); return; diff --git a/src/karts/kart_animation.hpp b/src/karts/kart_animation.hpp index bdcc6e1cf..0beac1e60 100644 --- a/src/karts/kart_animation.hpp +++ b/src/karts/kart_animation.hpp @@ -19,7 +19,7 @@ #ifndef HEADER_KART_ANIMATION_HPP #define HEADER_KART_ANIMATION_HPP -#include "utils/no_copy.hpp" +#include "karts/i_kart_animation.hpp" #include "utils/vec3.hpp" class Kart; @@ -38,7 +38,7 @@ class Stars; * explosion happens. * \ingroup karts */ -class KartAnimation: public NoCopy +class KartAnimation: public I_KartAnimation { protected: /** The coordinates where the kart was hit originally. */ @@ -65,9 +65,6 @@ protected: /** A pointer to the class to which this object belongs. */ Kart *m_kart; - /** True if this kart has been eliminated. */ - bool m_eliminated; - /** For stars rotating around head effect */ Stars *m_stars_effect; @@ -86,25 +83,10 @@ public: virtual void rescue(bool is_auto_rescue=false); virtual void shootTo(const Vec3 &target, float speed); void update(float dt); - void eliminate (bool remove); - // ------------------------------------------------------------------------ - /** Returns true if an animation is being played. */ - bool playingAnimation() const {return m_kart_mode!=KA_NONE; } - // ------------------------------------------------------------------------ - /** Returns if a rescue animation is being shown. */ - bool playingRescueAnimation() const {return m_kart_mode==KA_RESCUE; } - // ------------------------------------------------------------------------ - /** Returns if an explosion animation is being shown. */ - bool playingExplosionAnimation() const {return m_kart_mode==KA_EXPLOSION;} - // ------------------------------------------------------------------------ - /** Returns the timer for the currently played animation. */ - const float getAnimationTimer() const {return m_timer;} - // ------------------------------------------------------------------------ - /** Returns true if the kart is eliminated. */ - bool isEliminated () const {return m_eliminated;} + void eliminate(); // ------------------------------------------------------------------------ /** Returns a pointer to the stars effect. */ const Stars *getStarEffect () const {return m_stars_effect; } -}; // KartAnimation +}; // KartAnimationAll #endif diff --git a/src/karts/kart_with_stats.cpp b/src/karts/kart_with_stats.cpp index 45af83251..573a4bf6c 100644 --- a/src/karts/kart_with_stats.cpp +++ b/src/karts/kart_with_stats.cpp @@ -18,7 +18,8 @@ #include "karts/kart_with_stats.hpp" -#include "karts/kart_animation.hpp" +#include "karts/explosion_animation.hpp" +#include "karts/rescue_animation.hpp" #include "items/item.hpp" KartWithStats::KartWithStats(const std::string& ident, @@ -62,45 +63,24 @@ void KartWithStats::update(float dt) } // update // ---------------------------------------------------------------------------- -/** Called when an explosion should be triggered. If the explosion actually - * happens (i.e. the kart is neither invulnerable nor is it already playing - * an emergency animation), it increases the number of times a kart was - * exploded, and adds up the overall time spent in animation as well. - * \param pos The position of the explosion. - * \param direct_hit If the kart was hit directly, or if this is only a - * seconday hit. +/** Overloading setKartAnimation with a kind of listener function in order + * to gather statistics about rescues and explosions. */ -void KartWithStats::handleExplosion(const Vec3& pos, bool direct_hit) +void KartWithStats::setKartAnimation(AbstractKartAnimation *ka) { - bool is_new_explosion = !playingEmergencyAnimation() && !isInvulnerable(); - Kart::explode(pos, direct_hit); - // If a kart is too far away from an explosion to be affected, its timer - // will be 0, and this should then not be counted as an explosion. - if(is_new_explosion && m_kart_animation->getAnimationTimer()>0) + bool is_new_explosion = !getKartAnimation() && !isInvulnerable(); + Kart::setKartAnimation(ka); + if(dynamic_cast(ka)) { m_explosion_count ++; - m_explosion_time += m_kart_animation->getAnimationTimer(); + m_explosion_time += ka->getAnimationTimer(); } - -} // handleExplosion - -// ---------------------------------------------------------------------------- -/** Called when a kart is being rescued. It counts the number of times a - * kart is being rescued, and sums up the time for rescue as well. - * \param is_auto_rescue True if this is an automatically triggered rescue. - */ -void KartWithStats::forceRescue(bool is_auto_rescue) -{ - bool is_new_rescue = !playingEmergencyAnimation(); - Kart::rescue(is_auto_rescue); - - // If there wasn't already a rescue happening, count this event: - if(is_new_rescue) + else if(dynamic_cast(ka)) { - m_rescue_count++; - m_rescue_time += m_kart_animation->getAnimationTimer(); + m_rescue_count ++; + m_rescue_time += ka->getAnimationTimer(); } -} // forceRescue +} // setKartAnimation // ---------------------------------------------------------------------------- /** Called when an item is collected. It will increment private variables that diff --git a/src/karts/kart_with_stats.hpp b/src/karts/kart_with_stats.hpp index 8cacc00bf..49d56aaee 100644 --- a/src/karts/kart_with_stats.hpp +++ b/src/karts/kart_with_stats.hpp @@ -71,9 +71,8 @@ public: const btTransform& init_transform); virtual void update(float dt); virtual void reset(); - virtual void handleExplosion(const Vec3& pos, bool direct_hit); - virtual void forceRescue(bool is_auto_rescue=false); virtual void collectedItem(Item *item, int add_info); + virtual void setKartAnimation(AbstractKartAnimation *ka); /** Returns the top speed of this kart. */ float getTopSpeed() const { return m_top_speed; } diff --git a/src/karts/rescue_animation.cpp b/src/karts/rescue_animation.cpp new file mode 100644 index 000000000..1a180673e --- /dev/null +++ b/src/karts/rescue_animation.cpp @@ -0,0 +1,99 @@ +// +// 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/rescue_animation.hpp" + +#include "graphics/referee.hpp" +#include "items/attachment.hpp" +#include "karts/abstract_kart.hpp" +#include "karts/kart_properties.hpp" +#include "modes/three_strikes_battle.hpp" +#include "modes/world.hpp" +#include "physics/physics.hpp" + +#include "ISceneNode.h" + +/** 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. + */ +RescueAnimation::RescueAnimation(AbstractKart *kart, bool is_auto_rescue) + : AbstractKartAnimation(kart) +{ + m_referee = new Referee(*m_kart); + m_kart->getNode()->addChild(m_referee->getSceneNode()); + m_timer = m_kart->getKartProperties()->getRescueTime(); + m_velocity = m_kart->getKartProperties()->getRescueHeight() / m_timer; + m_xyz = m_kart->getXYZ(); + + m_kart->getAttachment()->clear(); + + m_curr_rotation.setPitch(m_kart->getPitch()); + m_curr_rotation.setRoll(m_kart->getRoll() ); + m_curr_rotation.setHeading(0); + m_add_rotation = -m_curr_rotation/m_timer; + m_curr_rotation.setHeading(m_kart->getHeading()); + + World::getWorld()->getPhysics()->removeKart(m_kart); + + // Add a hit unless it was auto-rescue + if(race_manager->getMinorMode()==RaceManager::MINOR_MODE_3_STRIKES && + !is_auto_rescue) + { + ThreeStrikesBattle *world=(ThreeStrikesBattle*)World::getWorld(); + world->kartHit(m_kart->getWorldKartId()); + } +}; // RescueAnimation + +//----------------------------------------------------------------------------- +/** This object is automatically destroyed when the timer expires. + */ +RescueAnimation::~RescueAnimation() +{ + // If m_timer >=0, this object is deleted because the kart + // is deleted (at the end of a race), which means that + // world is in the process of being deleted. In this case + // we can't call removeKartAfterRescue() or getPhysics anymore. + if(m_timer < 0) + World::getWorld()->moveKartAfterRescue(m_kart); + m_kart->getNode()->removeChild(m_referee->getSceneNode()); + delete m_referee; + m_referee = NULL; + m_kart->getBody()->setLinearVelocity(btVector3(0,0,0)); + m_kart->getBody()->setAngularVelocity(btVector3(0,0,0)); + World::getWorld()->getPhysics()->addKart(m_kart); +} // ~RescueAnimation + +// ---------------------------------------------------------------------------- +/** Updates the kart animation. + * \param dt Time step size. + * \return True if the explosion is still shown, false if it has finished. + */ +void RescueAnimation::update(float dt) +{ + + m_xyz.setY(m_xyz.getY() + dt*m_velocity); + 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); + + AbstractKartAnimation::update(dt); + +} // update diff --git a/src/karts/rescue_animation.hpp b/src/karts/rescue_animation.hpp new file mode 100644 index 000000000..9b859a357 --- /dev/null +++ b/src/karts/rescue_animation.hpp @@ -0,0 +1,61 @@ +// +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2012 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_RESCUE_ANIMATION_HPP +#define HEADER_RESCUE_ANIMATION_HPP + +#include "karts/abstract_kart_animation.hpp" +#include "utils/vec3.hpp" + +class AbstractKart; +class Referee; + +/** This triggers a rescue of the specified kart. + * \ingroup karts + */ +class RescueAnimation: public AbstractKartAnimation +{ +protected: + /** The coordinates where the kart was hit originally. */ + Vec3 m_xyz; + + /** The kart's current rotation. */ + Vec3 m_curr_rotation; + + /** The artificial rotation to toss the kart around. It's in units + * of rotation per second. */ + Vec3 m_add_rotation; + + /** The velocity with which the kart is moved. */ + float m_velocity; + + /** Duration for the animation. 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; + + /** The referee during a rescue operation. */ + Referee *m_referee; + +public: + RescueAnimation(AbstractKart *kart, bool is_auto_rescue=false); + virtual ~RescueAnimation(); + virtual void update(float dt); + virtual const std::string getName() const { return "Rescue"; } +}; // RescueAnimation +#endif diff --git a/src/modes/linear_world.cpp b/src/modes/linear_world.cpp index 3b6b74b23..ac0a5137c 100644 --- a/src/modes/linear_world.cpp +++ b/src/modes/linear_world.cpp @@ -156,7 +156,7 @@ void LinearWorld::update(float dt) // Nothing to do for karts that are currently being // rescued or eliminated - if(kart->playingEmergencyAnimation()) continue; + if(kart->getKartAnimation()) continue; kart_info.getSector()->update(kart->getXYZ()); } // for n @@ -801,7 +801,7 @@ void LinearWorld::checkForWrongDirection(unsigned int i) { if(!m_karts[i]->getController()->isPlayerController()) return; if(!m_kart_info[i].getSector()->isOnRoad()|| - m_karts[i]->playingEmergencyAnimation()) return; + m_karts[i]->getKartAnimation()) return; const AbstractKart *kart=m_karts[i]; // If the kart can go in more than one directions from the current track diff --git a/src/modes/three_strikes_battle.cpp b/src/modes/three_strikes_battle.cpp index 326a37613..95b852a41 100644 --- a/src/modes/three_strikes_battle.cpp +++ b/src/modes/three_strikes_battle.cpp @@ -151,8 +151,7 @@ void ThreeStrikesBattle::kartHit(const int kart_id) if(wheels[1]) wheels[1]->setVisible(false); if(wheels[2]) wheels[2]->setVisible(false); if(wheels[3]) wheels[3]->setVisible(false); - eliminateKart(kart_id, /*notify_of_elimination*/ true, - /*remove*/true); + eliminateKart(kart_id, /*notify_of_elimination*/ true); m_insert_tire = 4; } diff --git a/src/modes/world.cpp b/src/modes/world.cpp index 8aedcc5f9..fe8c8122a 100644 --- a/src/modes/world.cpp +++ b/src/modes/world.cpp @@ -831,8 +831,7 @@ AbstractKart *World::getLocalPlayerKart(unsigned int n) const //----------------------------------------------------------------------------- /** Remove (eliminate) a kart from the race */ -void World::eliminateKart(int kart_number, bool notify_of_elimination, - bool remove) +void World::eliminateKart(int kart_number, bool notify_of_elimination) { AbstractKart *kart = m_karts[kart_number]; @@ -870,7 +869,7 @@ void World::eliminateKart(int kart_number, bool notify_of_elimination, // ignored in all loops). Important:world->getCurrentNumKarts() returns // the number of karts still racing. This value can not be used for loops // over all karts, use race_manager->getNumKarts() instead! - kart->eliminate(remove); + kart->eliminate(); m_eliminated_karts++; } // removeKart diff --git a/src/modes/world.hpp b/src/modes/world.hpp index a081bd825..a9e41e5e0 100644 --- a/src/modes/world.hpp +++ b/src/modes/world.hpp @@ -90,8 +90,7 @@ protected: std::string* highscore_who, StateManager::ActivePlayer** best_player); void resetAllKarts (); - void eliminateKart (int kart_number, bool notifyOfElimination=true, - bool remove=true); + void eliminateKart (int kart_number, bool notifyOfElimination=true); Controller* loadAIController (AbstractKart *kart); diff --git a/src/network/race_state.cpp b/src/network/race_state.cpp index ea10d9391..5cca0a184 100644 --- a/src/network/race_state.cpp +++ b/src/network/race_state.cpp @@ -16,10 +16,12 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -#include "modes/world.hpp" -#include "network/network_manager.hpp" #include "network/race_state.hpp" #include "items/item_manager.hpp" + +#include "karts/rescue_animation.hpp" +#include "modes/world.hpp" +#include "network/network_manager.hpp" #include "items/powerup.hpp" #include "items/projectile_manager.hpp" @@ -141,7 +143,7 @@ void RaceState::receive(ENetPacket *pkt) { ItemInfo hi(this); if(hi.m_item_id==-1) // Rescue triggered - world->getKart(hi.m_kart_id)->rescue(); + new RescueAnimation(world->getKart(hi.m_kart_id)); else item_manager->collectedItem(hi.m_item_id, world->getKart(hi.m_kart_id), diff --git a/src/physics/physics.cpp b/src/physics/physics.cpp index 1f30e79f0..7f2112cbb 100644 --- a/src/physics/physics.cpp +++ b/src/physics/physics.cpp @@ -21,6 +21,7 @@ #include "animations/three_d_animation.hpp" #include "config/user_config.hpp" #include "karts/kart_properties.hpp" +#include "karts/rescue_animation.hpp" #include "network/race_state.hpp" #include "graphics/stars.hpp" #include "physics/btKart.hpp" @@ -73,12 +74,20 @@ Physics::~Physics() // ---------------------------------------------------------------------------- /** Adds a kart to the physics engine. - * This adds the rigid body, the vehicle, and the upright constraint. + * This adds the rigid body, the vehicle, and the upright constraint, but only + * if the kart is not already in the physics world. * \param kart The kart to add. * \param vehicle The raycast vehicle object. */ void Physics::addKart(const AbstractKart *kart) { + const btCollisionObjectArray &all_objs = + m_dynamics_world->getCollisionObjectArray(); + for(unsigned int i=0; i<(unsigned int)all_objs.size(); i++) + { + if(btRigidBody::upcast(all_objs[i])== kart->getBody()) + return; + } m_dynamics_world->addRigidBody(kart->getBody()); m_dynamics_world->addVehicle(kart->getVehicle()); m_dynamics_world->addConstraint(kart->getUprightConstraint()); @@ -145,7 +154,7 @@ void Physics::update(float dt) if(obj->isCrashReset()) { AbstractKart *kart = p->getUserPointer(1)->getPointerKart(); - kart->rescue(); + new RescueAnimation(kart); } continue; } @@ -157,7 +166,7 @@ void Physics::update(float dt) if(anim->isCrashReset()) { AbstractKart *kart = p->getUserPointer(1)->getPointerKart(); - kart->rescue(); + new RescueAnimation(kart); } continue; diff --git a/src/states_screens/race_gui_base.cpp b/src/states_screens/race_gui_base.cpp index ecb58dd01..001d51b2b 100644 --- a/src/states_screens/race_gui_base.cpp +++ b/src/states_screens/race_gui_base.cpp @@ -39,10 +39,14 @@ #include "io/file_manager.hpp" #include "items/attachment_manager.hpp" #include "items/powerup.hpp" -#include "karts/controller/controller.hpp" #include "karts/abstract_kart.hpp" +#include "karts/abstract_kart_animation.hpp" +#include "karts/canon_animation.hpp" +#include "karts/controller/controller.hpp" +#include "karts/explosion_animation.hpp" #include "karts/kart_properties.hpp" #include "karts/kart_properties_manager.hpp" +#include "karts/rescue_animation.hpp" #include "modes/follow_the_leader.hpp" #include "modes/world.hpp" #include "tracks/track.hpp" @@ -788,7 +792,7 @@ void RaceGUIBase::drawGlobalPlayerIcons(const KartIconDisplayInfo* info, unsigned int kart_id = kart->getWorldKartId(); //x,y is the target position - int lap = info[kart->getWorldKartId()].lap; + int lap = info[kart_id].lap; // In battle mode there is no distance along track etc. if(race_manager->getMinorMode()==RaceManager::MINOR_MODE_3_STRIKES) @@ -801,8 +805,10 @@ void RaceGUIBase::drawGlobalPlayerIcons(const KartIconDisplayInfo* info, LinearWorld *linear_world = (LinearWorld*)(World::getWorld()); float distance = linear_world->getDistanceDownTrackForKart(kart_id) - + linear_world->getTrack()->getTrackLength()*lap; - if ((position>1) && (previous_distance-distancehasFinishedRace())) + + linear_world->getTrack()->getTrackLength()*lap; + if ((position>1) && + (previous_distance-distancehasFinishedRace()) ) { //linear translation : form (0,ICON_PLAYER_WIDTH+2) to // (previous_x-x_base+(ICON_PLAYER_WIDTH+2)/2,0) @@ -897,8 +903,7 @@ void RaceGUIBase::drawGlobalPlayerIcons(const KartIconDisplayInfo* info, } // Fixes crash bug, why are certain icons not showing up? - if ((icon != NULL) && (!kart->playingEmergencyAnimation()) && - (!kart->isSquashed()) ) + if (icon && !kart->getKartAnimation() && !kart->isSquashed()) { const core::rect rect(core::position2d(0,0), icon->getOriginalSize()); @@ -906,12 +911,13 @@ void RaceGUIBase::drawGlobalPlayerIcons(const KartIconDisplayInfo* info, NULL, NULL, true); } - //draw status info + //draw status info - icon fade out in case of rescue/explode - if ((icon != NULL) && (kart->playingRescueAnimation())) + if (icon && dynamic_cast(kart->getKartAnimation())) { //icon fades to the left - float t_anim=100*sin(0.5f*M_PI*kart->getAnimationTimer()); + float t = kart->getKartAnimation()->getAnimationTimer(); + float t_anim=100*sin(0.5f*M_PI*t); const core::rect rect1(core::position2d(0,0), icon->getOriginalSize()); const core::rect pos1((int)(x-t_anim), y, @@ -920,7 +926,7 @@ void RaceGUIBase::drawGlobalPlayerIcons(const KartIconDisplayInfo* info, NULL, NULL, true); } - if ((icon != NULL) && (!kart->playingEmergencyAnimation()) && (kart->isSquashed())) + if (icon && !kart->getKartAnimation() && kart->isSquashed() ) { //syncs icon squash with kart squash const core::rect destRect(core::position2d(x,y+w/4), @@ -932,10 +938,12 @@ void RaceGUIBase::drawGlobalPlayerIcons(const KartIconDisplayInfo* info, true); } - if ((icon != NULL) && (kart->playingExplosionAnimation())) + if (icon && + dynamic_cast(kart->getKartAnimation()) ) { //exploses into 4 parts - float t_anim=50.0f*sin(0.5f*M_PI*kart->getAnimationTimer()); + float t = kart->getKartAnimation()->getAnimationTimer(); + float t_anim=50.0f*sin(0.5f*M_PI*t); u16 icon_size_x=icon->getOriginalSize().Width; u16 icon_size_y=icon->getOriginalSize().Height; diff --git a/src/tracks/check_canon.cpp b/src/tracks/check_canon.cpp index 42a83c242..d5e90f3b8 100644 --- a/src/tracks/check_canon.cpp +++ b/src/tracks/check_canon.cpp @@ -20,6 +20,7 @@ #include "io/xml_node.hpp" #include "karts/abstract_kart.hpp" +#include "karts/canon_animation.hpp" #include "modes/world.hpp" /** Constructor for a check canon. @@ -46,5 +47,5 @@ void CheckCanon::trigger(unsigned int kart_index) { Vec3 target(m_target.getMiddle()); AbstractKart *kart = World::getWorld()->getKart(kart_index); - kart->shootTo(target, m_speed); + new CanonAnimation(kart, target, m_speed); } // CheckCanon diff --git a/src/tracks/check_structure.cpp b/src/tracks/check_structure.cpp index 590e5acdd..2a500c70d 100644 --- a/src/tracks/check_structure.cpp +++ b/src/tracks/check_structure.cpp @@ -100,6 +100,7 @@ void CheckStructure::update(float dt) for(unsigned int i=0; igetNumKarts(); i++) { const Vec3 &xyz = world->getKart(i)->getXYZ(); + if(world->getKart(i)->getKartAnimation()) continue; // Only check active checklines. if(m_is_active[i] && isTriggered(m_previous_position[i], xyz, i)) {