diff --git a/src/Makefile.am b/src/Makefile.am
index 22a402baf..29cdfbb4b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -68,6 +68,8 @@ supertuxkart_SOURCES = \
graphics/hardware_skinning.cpp \
graphics/hardware_skinning.hpp \
graphics/hit_effect.hpp \
+ graphics/hit_sfx.cpp \
+ graphics/hit_sfx.hpp \
graphics/irr_driver.cpp \
graphics/irr_driver.hpp \
graphics/lod_node.cpp \
diff --git a/src/graphics/explosion.cpp b/src/graphics/explosion.cpp
index cc8ca26c7..cb6cff000 100644
--- a/src/graphics/explosion.cpp
+++ b/src/graphics/explosion.cpp
@@ -33,14 +33,12 @@
const float burst_time = 0.1f;
/** Creates an explosion effect. */
-Explosion::Explosion(const Vec3& coord, const char* explosion_sound,
- bool player_kart_hit)
- : HitEffect(coord, explosion_sound, player_kart_hit)
-{
+Explosion::Explosion(const Vec3& coord, const char* explosion_sound)
+ : HitSFX(coord, explosion_sound)
+{
// short emision time, explosion, not constant flame
m_remaining_time = burst_time;
m_node = irr_driver->addParticleNode();
- m_player_kart_hit = player_kart_hit;
#ifdef DEBUG
m_node->setName("explosion");
@@ -73,17 +71,6 @@ Explosion::Explosion(const Vec3& coord, const char* explosion_sound,
m_node->createScaleParticleAffector(core::dimension2df(3.0f, 3.0f));
m_node->addAffector(scale_affector); // same goes for the affector
scale_affector->drop();
-
- m_explode_sound = sfx_manager->createSoundSource( explosion_sound );
- m_explode_sound->position(coord);
-
- // in multiplayer mode, sounds are NOT positional (because we have multiple listeners)
- // so the sounds of all AIs are constantly heard. So reduce volume of sounds.
- if (race_manager->getNumLocalPlayers() > 1)
- m_explode_sound->volume(m_player_kart_hit ? 1.0f : 0.5f);
- else
- m_explode_sound->volume(1.0f);
- m_explode_sound->play();
} // Explosion
//-----------------------------------------------------------------------------
@@ -91,12 +78,6 @@ Explosion::Explosion(const Vec3& coord, const char* explosion_sound,
*/
Explosion::~Explosion()
{
- if (m_explode_sound->getStatus() == SFXManager::SFX_PLAYING)
- {
- m_explode_sound->stop();
- }
-
- sfx_manager->deleteSFX(m_explode_sound);
} // ~Explosion
//-----------------------------------------------------------------------------
@@ -106,6 +87,10 @@ Explosion::~Explosion()
*/
bool Explosion::update(float dt)
{
+ // The explosion sfx is shorter than the particle effect,
+ // so no need to save the result of the update call.
+ HitSFX::update(dt);
+
m_remaining_time -= dt;
if (m_remaining_time < 0.0f && m_remaining_time >= -explosion_time)
@@ -133,11 +118,6 @@ bool Explosion::update(float dt)
// Otherwise check that the sfx has finished, otherwise the
// sfx will get aborted 'in the middle' when this explosion
// object is removed.
- //if (m_explode_sound->getStatus() == SFXManager::SFX_PLAYING)
- //{
- // m_remaining_time = 0;
- //}
- //else
if (m_remaining_time > -explosion_time)
{
// Stop the emitter and wait a little while for all particles to have time to fade out
diff --git a/src/graphics/explosion.hpp b/src/graphics/explosion.hpp
index 56c1b05c3..460093d31 100644
--- a/src/graphics/explosion.hpp
+++ b/src/graphics/explosion.hpp
@@ -20,7 +20,7 @@
#ifndef HEADER_EXPLOSION_HPP
#define HEADER_EXPLOSION_HPP
-#include "graphics/hit_effect.hpp"
+#include "graphics/hit_sfx.hpp"
#include "utils/no_copy.hpp"
namespace irr
@@ -37,16 +37,14 @@ const float explosion_time = 1.5f;
/**
* \ingroup graphics
*/
-class Explosion : public HitEffect
+class Explosion : public HitSFX
{
private:
- SFXBase* m_explode_sound;
float m_remaining_time;
- bool m_player_kart_hit;
scene::IParticleSystemSceneNode *m_node;
public:
- Explosion(const Vec3& coord, const char* explosion_sound, bool player_hit);
+ Explosion(const Vec3& coord, const char* explosion_sound);
~Explosion();
bool update (float delta_t);
bool hasEnded () { return m_remaining_time <= -explosion_time; }
diff --git a/src/graphics/hit_effect.hpp b/src/graphics/hit_effect.hpp
index 1a68b1d55..4078b62d4 100644
--- a/src/graphics/hit_effect.hpp
+++ b/src/graphics/hit_effect.hpp
@@ -32,15 +32,28 @@ class Vec3;
*/
class HitEffect: public NoCopy
{
+private:
+ /** True if this effect affected a player kart. Used to play certain SFX
+ * less loud if only an AI is hit. */
+ bool m_player_kart_hit;
+
public:
- /** Constructor for a hit effect. */
- HitEffect(const Vec3& coord, const char* explosion_sound,
- bool player_hit) {};
- virtual ~HitEffect() {};
+ /** Constructor for a hit effect. */
+ HitEffect() {m_player_kart_hit = false; }
+ virtual ~HitEffect() {}
/** Updates a hit effect. Called once per frame.
* \param dt Time step size.
* \return True if the hit effect is finished and can be removed. */
virtual bool update (float dt) = 0;
+
+ // ------------------------------------------------------------------------
+ /** Sets that this SFX affects a player kart, which can be used to
+ * make certain sfx louder/less loud. Default is that the affect
+ * does not affect a player kart. */
+ virtual void setPlayerKartHit() { m_player_kart_hit = true; }
+ // ------------------------------------------------------------------------
+ /** Returns if this effect affects a player kart. */
+ bool getPlayerKartHit() const { return m_player_kart_hit; }
}; // HitEffect
#endif
diff --git a/src/graphics/hit_sfx.cpp b/src/graphics/hit_sfx.cpp
new file mode 100644
index 000000000..d0616d5f4
--- /dev/null
+++ b/src/graphics/hit_sfx.cpp
@@ -0,0 +1,71 @@
+// $Id$
+//
+// SuperTuxKart - a fun racing game with go-kart
+// Copyright (C) 2011 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 "graphics/hit_sfx.hpp"
+
+#include "audio/sfx_base.hpp"
+#include "audio/sfx_manager.hpp"
+#include "race/race_manager.hpp"
+
+/** Creates a sound effect when something was hit. */
+HitSFX::HitSFX(const Vec3& coord, const char* explosion_sound)
+ : HitEffect()
+{
+ m_sfx = sfx_manager->createSoundSource( explosion_sound );
+ m_sfx->position(coord);
+
+ // in multiplayer mode, sounds are NOT positional (because we have
+ // multiple listeners) so the sounds of all AIs are constantly heard.
+ // Therefore reduce volume of sounds.
+ float vol = race_manager->getNumLocalPlayers() > 1 ? 0.5f : 1.0f;
+ m_sfx->volume(vol);
+ m_sfx->play();
+} // HitSFX
+
+//-----------------------------------------------------------------------------
+/** Destructor stops the explosion sfx from being played and frees its memory.
+ */
+HitSFX::~HitSFX()
+{
+ if (m_sfx->getStatus() == SFXManager::SFX_PLAYING)
+ m_sfx->stop();
+
+ sfx_manager->deleteSFX(m_sfx);
+} // ~HitEffect
+
+//-----------------------------------------------------------------------------
+/** Called if this hit effect is for a player kart (in which case it might be
+ * played louder than for a non-player kart if split screen is used).
+ * If this sfx is for a player kart in split screen, make it louder again.
+ */
+void HitSFX::setPlayerKartHit()
+{
+ if(race_manager->getNumLocalPlayers())
+ m_sfx->volume(1.0f);
+} // setPlayerKartHit
+
+//-----------------------------------------------------------------------------
+/** Updates the hit sfx, called one per time step.
+ * \param dt Time step size.
+ * \return true If the explosion is finished.
+ */
+bool HitSFX::update(float dt)
+{
+ return m_sfx->getStatus() != SFXManager::SFX_PLAYING;
+} // update
diff --git a/src/graphics/hit_sfx.hpp b/src/graphics/hit_sfx.hpp
new file mode 100644
index 000000000..a0ad16cec
--- /dev/null
+++ b/src/graphics/hit_sfx.hpp
@@ -0,0 +1,46 @@
+// $Id$
+//
+// SuperTuxKart - a fun racing game with go-kart
+// Copyright (C) 2011 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_HIT_SFX_HPP
+#define HEADER_HIT_SFX_HPP
+
+#include "graphics/hit_effect.hpp"
+
+class SFXBase;
+
+/**
+ * \ingroup graphics
+ */
+class HitSFX : public HitEffect
+{
+private:
+ /** The sfx to play. */
+ SFXBase* m_sfx;
+
+public:
+ HitSFX(const Vec3& coord, const char* explosion_sound);
+ ~HitSFX();
+ virtual bool update (float dt);
+ virtual void setPlayerKartHit();
+
+}; // HitSFX
+
+#endif
+
+/* EOF */
diff --git a/src/ide/vc9/supertuxkart.vcproj b/src/ide/vc9/supertuxkart.vcproj
index 7d1be5a04..ba5fde863 100644
--- a/src/ide/vc9/supertuxkart.vcproj
+++ b/src/ide/vc9/supertuxkart.vcproj
@@ -702,6 +702,10 @@
RelativePath="..\..\graphics\hardware_skinning.cpp"
>
+
+
@@ -1788,6 +1792,10 @@
RelativePath="..\..\graphics\hit_effect.hpp"
>
+
+
diff --git a/src/items/attachment.cpp b/src/items/attachment.cpp
index 067ee095d..80da7bc79 100644
--- a/src/items/attachment.cpp
+++ b/src/items/attachment.cpp
@@ -23,6 +23,7 @@
#include "audio/sfx_base.hpp"
#include "config/stk_config.hpp"
#include "config/user_config.hpp"
+#include "graphics/explosion.hpp"
#include "graphics/irr_driver.hpp"
#include "items/attachment_manager.hpp"
#include "items/projectile_manager.hpp"
@@ -179,8 +180,11 @@ void Attachment::hitBanana(Item *item, int new_attachment)
case ATTACH_BOMB:
{
add_a_new_item = false;
- projectile_manager->newHitEffect(m_kart->getXYZ(), "explosion",
- m_kart->getController()->isPlayerController());
+ HitEffect *he = new Explosion(m_kart->getXYZ(), "explosion");
+ if(m_kart->getController()->isPlayerController())
+ he->setPlayerKartHit();
+ projectile_manager->addHitEffect(he);
+
m_kart->handleExplosion(m_kart->getXYZ(), /*direct_hit*/ true);
clear();
if(new_attachment==-1)
@@ -313,8 +317,10 @@ void Attachment::update(float dt)
}
if(m_time_left<=0.0)
{
- projectile_manager->newHitEffect(m_kart->getXYZ(), "explosion",
- m_kart->getController()->isPlayerController());
+ HitEffect *he = new Explosion(m_kart->getXYZ(), "explosion");
+ if(m_kart->getController()->isPlayerController())
+ he->setPlayerKartHit();
+ projectile_manager->addHitEffect(he);
m_kart->handleExplosion(m_kart->getXYZ(),
/*direct_hit*/ true);
diff --git a/src/items/flyable.cpp b/src/items/flyable.cpp
index 69df92bfa..4c9edf5c5 100644
--- a/src/items/flyable.cpp
+++ b/src/items/flyable.cpp
@@ -30,6 +30,7 @@
#include
#include
+#include "graphics/explosion.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/mesh_tools.hpp"
#include "graphics/stars.hpp"
@@ -539,5 +540,13 @@ void Flyable::hit(Kart *kart_hit, PhysicalObject* object)
}
world->getTrack()->handleExplosion(getXYZ(), object);
} // hit
+// ----------------------------------------------------------------------------
+/** Returns the hit effect object to use when this objects hits something.
+ * \returns The hit effect object, or NULL if no hit effect should be played.
+ */
+HitEffect* Flyable::getHitEffect() const
+{
+ return new Explosion(getXYZ(), "explosion");
+} // getHitEffect
/* EOF */
diff --git a/src/items/flyable.hpp b/src/items/flyable.hpp
index e18dd87d2..44926edaa 100644
--- a/src/items/flyable.hpp
+++ b/src/items/flyable.hpp
@@ -35,6 +35,7 @@ using namespace irr;
#include "tracks/terrain_info.hpp"
class FlyableInfo;
+class HitEffect;
class Kart;
class PhysicalObject;
class XMLNode;
@@ -155,6 +156,7 @@ public:
PowerupManager::PowerupType type);
virtual void update (float);
void updateFromServer(const FlyableInfo &f, float dt);
+ HitEffect *getHitEffect() const;
bool isOwnerImmunity(const Kart *kart_hit) const;
// ------------------------------------------------------------------------
diff --git a/src/items/projectile_manager.cpp b/src/items/projectile_manager.cpp
index f0ca612ce..1951753c3 100644
--- a/src/items/projectile_manager.cpp
+++ b/src/items/projectile_manager.cpp
@@ -85,8 +85,8 @@ void ProjectileManager::update(float dt)
if(! (*p)->hasHit()) { p++; continue; }
if((*p)->needsExplosion())
{
- newHitEffect((*p)->getXYZ(), (*p)->getExplosionSound(),
- /*player_kart_hit*/ false );
+ HitEffect *he = (*p)->getHitEffect();
+ addHitEffect(he);
}
Flyable *f=*p;
Projectiles::iterator pNext=m_active_projectiles.erase(p); // returns the next element
@@ -176,47 +176,3 @@ Flyable *ProjectileManager::newProjectile(Kart *kart,
m_active_projectiles.push_back(f);
return f;
} // newProjectile
-
-// -----------------------------------------------------------------------------
-/** Creates a new hit effect.
- * \param coord The coordinates where the hit effect (i.e. sound, graphics)
- * should be placed).
- * \param sfx The name of the sound effect to be played.
- * \param player_kart_hit True of a player kart was hit.
- */
-HitEffect* ProjectileManager::newHitEffect(const Vec3& coord,
- const char *sfx,
- bool player_kart_hit)
-{
- HitEffect *he = new Explosion(coord, sfx, player_kart_hit);
- m_active_hit_effects.push_back(he);
- return he;
-} // newHitEffect
-
-// =============================================================================
-/** A general function which is only needed here, but
- * it's not really a method, so I'll leave it here.
- */
-/*
-static ssgSelector *find_selector ( ssgBranch *b )
-{
- if ( b == NULL )
- return NULL ;
-
- if ( ! b -> isAKindOf ( ssgTypeBranch () ) )
- return NULL ;
-
- if ( b -> isAKindOf ( ssgTypeSelector () ) )
- return (ssgSelector *) b ;
-
- for ( int i = 0 ; i < b -> getNumKids() ; i++ )
- {
- ssgSelector *res = find_selector ( (ssgBranch *)(b ->getKid(i)) ) ;
-
- if ( res != NULL )
- return res ;
- }
-
- return NULL ;
-} // find_selector
-*/
diff --git a/src/items/projectile_manager.hpp b/src/items/projectile_manager.hpp
index f663d1441..8469dec1b 100644
--- a/src/items/projectile_manager.hpp
+++ b/src/items/projectile_manager.hpp
@@ -53,8 +53,6 @@ private:
* being shown or have a sfx playing. */
HitEffects m_active_hit_effects;
- scene::IMesh *m_explosion_model;
-
bool m_something_was_hit;
void updateClient(float dt);
void updateServer(float dt);
@@ -63,20 +61,18 @@ public:
~ProjectileManager() {}
/** Notifies the projectile manager that something needs to be removed. */
void notifyRemove () {m_something_was_hit=true; }
- scene::IMesh *getExplosionModel()
- {
- return m_explosion_model;
- }
void loadData ();
void cleanup ();
void update (float dt);
Flyable* newProjectile (Kart *kart,
PowerupManager::PowerupType type);
- HitEffect* newHitEffect (const Vec3& coord,
- const char* explosion_sound="explosion",
- bool is_player_kart_hit = false);
void Deactivate (Flyable *p) {}
void removeTextures ();
+ // ------------------------------------------------------------------------
+ /** Adds a special hit effect to be shown.
+ * \param hit_effect The hit effect to be added. */
+ void addHitEffect(HitEffect *hit_effect)
+ { m_active_hit_effects.push_back(hit_effect); }
};
extern ProjectileManager *projectile_manager;
diff --git a/src/items/rubber_ball.cpp b/src/items/rubber_ball.cpp
index 3156ab4ea..1d8fdf333 100644
--- a/src/items/rubber_ball.cpp
+++ b/src/items/rubber_ball.cpp
@@ -423,7 +423,9 @@ void RubberBall::hit(Kart* kart, PhysicalObject* object)
{
// If the object is not the main target, only flatten the kart
if(kart!=m_target)
+ {
kart->setSquash(m_st_squash_duration, m_st_squash_slowdown);
+ }
else
{
// Else trigger the full explosion animation