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