00001 /******************************************************************************* 00002 This file is Part of the ZEngine Library for 2D game development. 00003 Copyright (C) 2002, 2003 James Turk 00004 00005 Licensed under a BSD-style license. 00006 00007 The maintainer of this library is James Turk (james@conceptofzero.net) 00008 and the home of this Library is http://www.zengine.sourceforge.net 00009 *******************************************************************************/ 00010 00021 #ifndef __ze_zbaseparticlesystem_h__ 00022 #define __ze_zbaseparticlesystem_h__ 00023 00024 #include "ZEngine.h" 00025 00026 namespace ZE 00027 { 00028 00035 class ZBaseParticle 00036 { 00037 public: 00043 virtual ~ZBaseParticle() 00044 {} // empty definition here, since ZBaseParticleSystem has no cpp file and this would be all that would be in it 00045 00047 float xPos; 00049 float yPos; 00051 float energy; 00052 }; 00053 00062 template <class particleType> 00063 class ZBaseParticleSystem 00064 { 00065 protected: 00067 ZEngine *rEngine; 00069 particleType *rParticles; 00071 unsigned int rMaxParticles; 00073 unsigned int rCurParticles; 00075 unsigned int rNumParticlesPerSec; 00077 Uint32 rLastUpdate; 00079 bool rPaused; 00080 00086 void AddParticle(); 00087 00093 virtual particleType NewParticle()=0; 00094 00102 virtual void UpdateParticle(int index, float elapsedTime)=0; 00103 00104 public: 00110 ZBaseParticleSystem(); 00111 00117 virtual ~ZBaseParticleSystem(); 00118 00124 virtual void Render()=0; 00125 00132 void Emit(int numParticles); 00133 00141 virtual void Update(); 00142 00148 void Clear(); 00149 00155 void Pause(); 00156 00162 void Unpause(); 00163 00169 void Stop(); 00170 00177 bool Paused(); 00178 00186 void SetMaxParticles(unsigned int max); 00187 00194 void SetRate(unsigned int rate); 00195 }; 00196 00197 //implementation// 00198 00199 template <class particleType> 00200 void ZBaseParticleSystem<particleType>::AddParticle() 00201 { 00202 //empty space is always at end, function is private so no checking is needed (Emit does that) 00203 rParticles[rCurParticles] = NewParticle(); 00204 ++rCurParticles; 00205 } 00206 00207 template <class particleType> 00208 ZBaseParticleSystem<particleType>::ZBaseParticleSystem() 00209 { 00210 rEngine = ZEngine::GetInstance(); 00211 rParticles = NULL; 00212 rMaxParticles = rCurParticles = rNumParticlesPerSec = 0; 00213 rLastUpdate = rEngine->GetTime(); 00214 rPaused = false; 00215 } 00216 00217 template <class particleType> 00218 ZBaseParticleSystem<particleType>::~ZBaseParticleSystem() 00219 { 00220 if(rParticles) 00221 delete []rParticles; 00222 } 00223 00224 template <class particleType> 00225 void ZBaseParticleSystem<particleType>::Emit(int numParticles) 00226 { 00227 while(numParticles > 0 && rCurParticles < rMaxParticles) 00228 { 00229 AddParticle(); 00230 --numParticles; 00231 } 00232 } 00233 00234 template <class particleType> 00235 void ZBaseParticleSystem<particleType>::Update() 00236 { 00237 float elapsed = (rEngine->GetTime()-rLastUpdate)/1000.0f; 00238 double emitAmount; 00239 static double overflow=0; 00240 00241 if(!rPaused) 00242 { 00243 //update every particle and remove dead particles 00244 for(unsigned int i=0; i < rCurParticles; ++i) 00245 { 00246 UpdateParticle(i,elapsed); 00247 if(rParticles[i].xPos < 0 || rParticles[i].xPos > rEngine->DisplayWidth() 00248 || rParticles[i].yPos < 0 || rParticles[i].yPos > rEngine->DisplayHeight() || rParticles[i].energy <= 0) 00249 { 00250 rParticles[i] = rParticles[--rCurParticles]; 00251 --i; //go back one to process that particle 00252 } 00253 } 00254 00255 emitAmount = elapsed*rNumParticlesPerSec; 00256 overflow += emitAmount - static_cast<int>(emitAmount); //only floating point portion of emitAmount 00257 Emit(static_cast<int>(emitAmount)); 00258 if(overflow >= .95) //a little lower than one, for tolerance 00259 { 00260 Emit(1); 00261 overflow = 0; //dump & clear overflow 00262 } 00263 } 00264 00265 rLastUpdate = rEngine->GetTime(); 00266 } 00267 00268 00269 template <class particleType> 00270 void ZBaseParticleSystem<particleType>::Clear() 00271 { 00272 rCurParticles = 0; 00273 } 00274 00275 template <class particleType> 00276 void ZBaseParticleSystem<particleType>::Pause() 00277 { 00278 rPaused = true; 00279 } 00280 00281 template <class particleType> 00282 void ZBaseParticleSystem<particleType>::Unpause() 00283 { 00284 rPaused = false; 00285 } 00286 00287 template <class particleType> 00288 void ZBaseParticleSystem<particleType>::Stop() 00289 { 00290 Clear(); 00291 Pause(); 00292 } 00293 00294 template <class particleType> 00295 bool ZBaseParticleSystem<particleType>::Paused() 00296 { 00297 return rPaused; 00298 } 00299 00300 template <class particleType> 00301 void ZBaseParticleSystem<particleType>::SetMaxParticles(unsigned int max) 00302 { 00303 particleType *temp; 00304 unsigned int i; 00305 00306 if(max) 00307 { 00308 if(max != rMaxParticles) //only do this if size changed 00309 { 00310 if(rCurParticles) 00311 { 00312 rCurParticles %= max; 00313 //copy current particles to temp 00314 temp = new particleType[rCurParticles]; 00315 for(i=0; i < rCurParticles; ++i) 00316 temp[i] = rParticles[i]; 00317 } 00318 00319 //change size of rParticles 00320 if(rParticles) 00321 delete []rParticles; 00322 rParticles = new particleType[max]; 00323 rMaxParticles = max; 00324 00325 if(rCurParticles) 00326 { 00327 //copy particles from temp back to rParticles 00328 for(i=0; i < rCurParticles; ++i) 00329 rParticles[i] = temp[i]; 00330 00331 delete []temp; 00332 } 00333 } 00334 } 00335 else 00336 { 00337 rMaxParticles = rCurParticles = 0; 00338 if(rParticles) 00339 delete []rParticles; 00340 } 00341 } 00342 00343 template <class particleType> 00344 void ZBaseParticleSystem<particleType>::SetRate(unsigned int rate) 00345 { 00346 rNumParticlesPerSec = rate; 00347 } 00348 00349 } //namespace ZE 00350 00351 #endif //__ze_zbaseparticlesystem_h__