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
1.5.1