particle_effect.cpp

Go to the documentation of this file.
00001 
00002 //            Copyright (C) 2004-2007 by The Allacrost Project
00003 //                         All Rights Reserved
00004 //
00005 // This code is licensed under the GNU GPL version 2. It is free software 
00006 // and you may modify it and/or redistribute it under the terms of this license.
00007 // See http://www.gnu.org/copyleft/gpl.html for details.
00009 
00010 #include "particle_effect.h"
00011 #include "particle_system.h"
00012 #include "video.h"
00013 #include "script.h"
00014 
00015 using namespace std;
00016 using namespace hoa_script;
00017 using namespace hoa_video::private_video;
00018 
00019 namespace hoa_video
00020 {
00021 
00022 
00023 //-----------------------------------------------------------------------------
00024 // ParticleEffect
00025 //-----------------------------------------------------------------------------
00026 
00027 ParticleEffect::ParticleEffect()
00028 {
00029   _alive = false;
00030   _x = _y = 0.0f;
00031   _attractor_x = _attractor_y = 0.0f;
00032   _age = 0.0f;
00033   _effect_def = NULL;
00034   _orientation = 0.0f;
00035 }
00036 
00037 
00038 //-----------------------------------------------------------------------------
00039 // _Draw: draws the effect. This is called by ParticleManager, not by API user
00040 //-----------------------------------------------------------------------------
00041 
00042 bool ParticleEffect::_Draw()
00043 {
00044   bool success = true;
00045 
00046   // move to the effect's location
00047   VideoManager->Move(_x, _y);
00048 
00049   list<ParticleSystem *>::iterator iSystem = _systems.begin();
00050   
00051   while(iSystem != _systems.end())
00052   {
00053     VideoManager->PushMatrix();
00054     if(!(*iSystem)->Draw())
00055     {
00056       VideoManager->PopMatrix();
00057       success = false;      
00058       if(VIDEO_DEBUG)
00059         cerr << "VIDEO ERROR: failed to draw system in ParticleEffect::_Update()" << endl;
00060     }   
00061     
00062     VideoManager->PopMatrix();
00063     ++iSystem;
00064   }
00065   
00066   glDisable(GL_STENCIL_TEST);
00067   glDisable(GL_ALPHA_TEST);
00068   glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
00069 
00070   
00071   return success;
00072 }
00073 
00074 
00075 //-----------------------------------------------------------------------------
00076 // Update: updates particle effect. Called by ParticleManager, not by user.
00077 //-----------------------------------------------------------------------------
00078 
00079 bool ParticleEffect::_Update(float frame_time)
00080 {
00081   _age += frame_time;
00082   _num_particles = 0;
00083   
00084   if(!_alive)
00085     return true;
00086   
00087   bool success = true;
00088 
00089   private_video::EffectParameters effect_parameters;
00090   effect_parameters.orientation = _orientation;
00091   
00092   // note we subtract the effect position to put the attractor point in effect
00093   // space instead of screen space
00094   effect_parameters.attractor_x = _attractor_x - _x;
00095   effect_parameters.attractor_y = _attractor_y - _y;
00096 
00097   list<ParticleSystem *>::iterator iSystem = _systems.begin();  
00098   
00099   while(iSystem != _systems.end())
00100   {
00101     if(!(*iSystem)->IsAlive())
00102     {
00103       (*iSystem)->Destroy();
00104       iSystem = _systems.erase(iSystem);
00105 
00106       if(_systems.empty())
00107         _alive = false;
00108     }
00109     else 
00110     {
00111       if(!(*iSystem)->Update(frame_time, effect_parameters))
00112       {
00113         success = false;
00114         if(VIDEO_DEBUG)
00115           cerr << "VIDEO ERROR: failed to update system in ParticleEffect::_Update()" << endl;        
00116       }
00117       
00118       _num_particles += (*iSystem)->GetNumParticles();      
00119       ++iSystem;
00120     }
00121   }
00122 
00123   return success;
00124 }
00125 
00126 
00127 //-----------------------------------------------------------------------------
00128 // Destroy: destroys the effect. Called by ParticleManager during _Update(), if
00129 //          this effect is not alive (i.e. IsAlive() returns false)
00130 //-----------------------------------------------------------------------------
00131 
00132 void ParticleEffect::_Destroy()
00133 {
00134   list<ParticleSystem *>::iterator iSystem = _systems.begin();
00135   
00136   while(iSystem != _systems.end())
00137   {
00138     (*iSystem)->Destroy();
00139     ++iSystem;
00140   }
00141 }
00142 
00143 
00144 //-----------------------------------------------------------------------------
00145 // Move: function for the API user to move the effect around to different
00146 //       locations
00147 //-----------------------------------------------------------------------------
00148 
00149 void ParticleEffect::Move(float x, float y)
00150 {
00151   _x = x;
00152   _y = y;
00153 }
00154 
00155 
00156 //-----------------------------------------------------------------------------
00157 // MoveRelative: function for API user to move the effect relative to its current
00158 //            position
00159 //-----------------------------------------------------------------------------
00160 
00161 void ParticleEffect::MoveRelative(float dx, float dy)
00162 {
00163   _x += dx;
00164   _y += dy;
00165 }
00166 
00167 
00168 //-----------------------------------------------------------------------------
00169 // SetOrientation: sets the orientation of the effect, which is added to the
00170 //                 orientation for each of the emitters
00171 //-----------------------------------------------------------------------------
00172 
00173 void ParticleEffect::SetOrientation(float angle)
00174 {
00175   _orientation = angle;
00176 }
00177 
00178 
00179 //-----------------------------------------------------------------------------
00180 // SetAttractorPoint: set the location of an attractor point. Any systems with
00181 //                    radial acceleration and user-defined attractor points
00182 //                    enabled will have particles gravitate toward this point
00183 //-----------------------------------------------------------------------------
00184 
00185 void ParticleEffect::SetAttractorPoint(float x, float y)
00186 {
00187   _attractor_x = x;
00188   _attractor_y = y;
00189 }
00190 
00191 
00192 //-----------------------------------------------------------------------------
00193 // IsAlive: returns true if effect is still alive. Used by ParticleManager
00194 //          so it knows when to destroy an effect.
00195 //-----------------------------------------------------------------------------
00196 
00197 bool ParticleEffect::IsAlive()
00198 {
00199   return _alive;
00200 }
00201 
00202 
00203 //-----------------------------------------------------------------------------
00204 // Stop: stops the effect. If kill_immediate is true, then the effect is stopped
00205 //       immediately. Otherwise, the particles which are still alive are allowed
00206 //       to keep drawing, but no new particles are emitted.
00207 //-----------------------------------------------------------------------------
00208 
00209 void ParticleEffect::Stop(bool kill_immediate)
00210 {
00211   if(kill_immediate)
00212   {
00213     // just set _alive to false, and the particle manager will remove it for us
00214     _alive = false;
00215   }
00216   else
00217   {
00218     // if we're not killing immediately, then calling Stop() just means to stop emitting NEW
00219     // particles, so go through each system and turn off its emitter
00220     
00221     list<ParticleSystem *>::iterator iSystem = _systems.begin();
00222     
00223     while(iSystem != _systems.end())
00224     {
00225       (*iSystem)->Stop();
00226       ++iSystem;
00227     }   
00228   }
00229 }
00230 
00231 
00232 //-----------------------------------------------------------------------------
00233 // GetNumParticles: returns the number of live particles for the entire effect
00234 //-----------------------------------------------------------------------------
00235 
00236 int32 ParticleEffect::GetNumParticles() const
00237 {
00238   return _num_particles;  
00239 }
00240 
00241 
00242 //-----------------------------------------------------------------------------
00243 // GetPosition: returns the current position of the effect
00244 //-----------------------------------------------------------------------------
00245 
00246 void ParticleEffect::GetPosition(float &x, float &y) const
00247 {
00248   x = _x;
00249   y = _y;
00250 }
00251 
00252 
00253 //-----------------------------------------------------------------------------
00254 // GetAge: returns the current age of the effect, i.e. how many seconds it has
00255 //         been since the effect was created
00256 //-----------------------------------------------------------------------------
00257 
00258 float ParticleEffect::GetAge() const
00259 {
00260   return _age;
00261 }
00262 
00263 
00264 } // namespace hoa_video

Generated on Fri Jul 6 23:11:20 2007 for Hero of Allacrost by  doxygen 1.5.1