1 //
2 //  SuperTuxKart - a fun racing game with go-kart
3 //  Copyright (C) 2004-2015 Steve Baker <sjbaker1@airmail.net>
4 //
5 //  This program is free software; you can redistribute it and/or
6 //  modify it under the terms of the GNU General Public License
7 //  as published by the Free Software Foundation; either version 3
8 //  of the License, or (at your option) any later version.
9 //
10 //  This program is distributed in the hope that it will be useful,
11 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 //  GNU General Public License for more details.
14 //
15 //  You should have received a copy of the GNU General Public License
16 //  along with this program; if not, write to the Free Software
17 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 
19 #include "graphics/explosion.hpp"
20 
21 #include "audio/sfx_base.hpp"
22 #include "audio/sfx_manager.hpp"
23 #include "config/stk_config.hpp"
24 #include "config/user_config.hpp"
25 #include "graphics/irr_driver.hpp"
26 #include "graphics/material.hpp"
27 #include "graphics/material_manager.hpp"
28 #include "graphics/particle_emitter.hpp"
29 #include "graphics/particle_kind_manager.hpp"
30 #include "graphics/stk_particle.hpp"
31 #include "items/projectile_manager.hpp"
32 #include "race/race_manager.hpp"
33 #include "utils/vec3.hpp"
34 
35 
36 /** Creates an explosion effect. */
Explosion(const Vec3 & coord,const char * explosion_sound,const char * particle_file)37 Explosion::Explosion(const Vec3& coord, const char* explosion_sound, const char * particle_file)
38                      : HitSFX(coord, explosion_sound)
39 {
40     // short emision time, explosion, not constant flame
41 
42     m_explosion_ticks = stk_config->time2Ticks(2.0f);
43     m_remaining_ticks = stk_config->time2Ticks(0.1f);
44     m_emission_frames = 0;
45 
46 #ifndef SERVER_ONLY
47     std::string filename = particle_file;
48 
49 #ifdef MOBILE_STK
50     // Use a lower quality effect on mobile for better performance
51     if (filename == "explosion.xml" ||
52         filename == "explosion_bomb.xml" ||
53         filename == "explosion_cake.xml")
54     {
55         filename = "explosion_low.xml";
56     }
57 #endif
58 
59     ParticleKindManager* pkm = ParticleKindManager::get();
60     ParticleKind* particles = pkm->getParticles(filename);
61     m_emitter = NULL;
62 
63     if (UserConfigParams::m_particles_effects > 1)
64     {
65         m_emitter = new ParticleEmitter(particles, coord,  NULL);
66         m_emitter->getNode()->setPreGenerating(false);
67     }
68 #endif
69 }   // Explosion
70 
71 //-----------------------------------------------------------------------------
72 /** Destructor stops the explosion sfx from being played and frees its memory.
73  */
~Explosion()74 Explosion::~Explosion()
75 {
76 #ifndef SERVER_ONLY
77     if(m_emitter)
78     {
79         delete m_emitter;
80     }
81 #endif
82 }   // ~Explosion
83 
84 //-----------------------------------------------------------------------------
85 /** Updates the explosion, called one per time step.
86  *  \param dt Time step size.
87  *  \return true If the explosion is finished.
88  */
updateAndDelete(int ticks)89 bool Explosion::updateAndDelete(int ticks)
90 {
91     // The explosion sfx is shorter than the particle effect,
92     // so no need to save the result of the update call.
93     HitSFX::updateAndDelete(ticks);
94 
95     m_emission_frames++;
96     m_remaining_ticks -= ticks;
97 
98     // Do nothing more if the animation is still playing
99     if (m_remaining_ticks>0) return false;
100 
101     // Otherwise check that the sfx has finished, otherwise the
102     // sfx will get aborted 'in the middle' when this explosion
103     // object is removed.
104     if (m_remaining_ticks > -m_explosion_ticks)
105     {
106 #ifndef SERVER_ONLY
107         // if framerate is very low, emit for at least a few frames, in case
108         // burst time is lower than the time of 1 frame
109         if (m_emission_frames > 2 && m_emitter != NULL)
110         {
111             // Stop the emitter and wait a little while for all particles to have time to fade out
112             m_emitter->getNode()->getEmitter()->setMinParticlesPerSecond(0);
113             m_emitter->getNode()->getEmitter()->setMaxParticlesPerSecond(0);
114         }
115 #endif
116     }
117     else
118     {
119         // Sound and animation finished, node can be removed now.
120         // Returning true will cause this node to be deleted by
121         // the projectile manager.
122         return true;   // finished
123     }
124 
125     return false;  // not finished
126 }   // updateAndDelete
127 
128