diff --git a/include/ZE_ZBaseParticleSystem.h b/include/ZE_ZBaseParticleSystem.h new file mode 100755 index 0000000..9ba5c2b --- /dev/null +++ b/include/ZE_ZBaseParticleSystem.h @@ -0,0 +1,276 @@ +/******************************************************************************* + This file is Part of the ZEngine Library for 2D game development. + Copyright (C) 2002, 2003 James Turk + + Licensed under a BSD-style license. + + The maintainer of this library is James Turk (james@conceptofzero.net) + and the home of this Library is http://www.zengine.sourceforge.net +*******************************************************************************/ + +/*! + \file ZE_ZBaseParticleSystem.h + \brief Definition and implementation file for the base of the ZEngine Particle System. + + Definition and implementation file for ZEngine particle system class ZBaseParticleSystem. + Due to problems with template classes the template implementation needs to be in the same file as the declaration. +
$id$
+ \author James Turk +**/ + +#ifndef __ze_zbaseparticlesystem_h__ +#define __ze_zbaseparticlesystem_h__ + +#include "ZEngine.h" + +namespace ZE +{ + +/*! + \brief Basic particle class for ZEngine particle systems. + + Basic particle class, all particles used should derive from this class so that needed members are available. + (No default constructor is needed because NewParticle should initialize members.) +**/ +class ZBaseParticle +{ + public: + /*! + \brief Virtual destructor. + + Empty virtual destructor to make inheritance safe. + **/ + virtual ~ZBaseParticle() + {} // empty definition here, since ZBaseParticleSystem has no cpp file and this would be all that would be in it + + //! X Position of particle. + float xPos; + //! Y Position of particle. + float yPos; + //! Energy of particle (particles die if energy is 0). + float energy; +}; + +/*! + \brief Base particle system, a virtual class defining an outline for a fully functional particle system. + + Virtual class providing outline of basic particle system, designed so that a working particle system can be + derived with minimal waste. Uses templated system to allow particle systems to work with their own types of + particles, the particleType template parameter must be a type that has the members of ZBaseParticle. + (Note: If you need a very specific particle system it's probably best to write your own fit to your needs.) +**/ +template +class ZBaseParticleSystem +{ + protected: + //! Pointer to ZEngine singleton. + ZEngine *rEngine; + //! Pointer to array of particles. + particleType *rParticles; + //! Maximum number of particles, and size of rParticles array. + unsigned int rMaxParticles; + //! Current number of particles. + unsigned int rCurParticles; + //! Number of particles to release per second. + unsigned int rNumParticlesPerSec; + //! Millisecond format time of last update. + Uint32 rLastUpdate; + + /*! + \brief Adds a new particle. + + Finds room in array with dead particle, and adds new particle using NewParticle, called by Emit. + **/ + void AddParticle(); + + /*! + \brief Pure virtual function to initialize and return a new particle. + + Pure virtual function, overload should set up a new particle with desired traits, called by AddParticle. + **/ + virtual particleType NewParticle()=0; + + /*! + \brief Pure virtual function to update a particle. + + Pure virtual function, overload should update the particle `rParticles[index]`, called by Update. + \param index Index of particle in rParticles array to update. + \param elapsedTime Decimal portion of a second since last call. + **/ + virtual void UpdateParticle(int index, float elapsedTime)=0; + + public: + /*! + \brief Basic constructor for ZBaseParticleSystem. + + Basic constructor for ZBaseParticle system, initializes all values to 0. + **/ + ZBaseParticleSystem(); + + /*! + \brief Virtual destructor for ZBaseParticleSystem. + + Virtual destructor for ZBaseParticleSystem, destroys all particles, virtual to make class inheritance-safe. + **/ + virtual ~ZBaseParticleSystem(); + + /*! + \brief Pure virtual function, renders the particles. + + Pure virtual so that each particle system can render it's member particles in it's own way. + **/ + virtual void Render()=0; + + /*! + \brief Emit a given number of particles. + + Emits a given number of particles, will not emit particles if system is full. + \param numParticles Number of particles to emit. + **/ + void Emit(int numParticles); + + /*! + \brief Updates status of particle system. + + Updates entire particle system, calling update on every particle, emitting necessary new + particles, removing particles which have an energy <= 0 or are off the screen. + **/ + void Update(); + + /*! + \brief Sets max particles allowed in system. + + Set maximum number of particles allowed in system, particles are not emitted when system is full. + When this resizes the array contents are moved to the new array, if it shrinks the array particles may be lost. + \param max Maximum number of particles for system. + **/ + void SetMaxParticles(int max); + + /*! + \brief Sets release rate of particles. + + Set number of particles to release per second. + \param rate Number of particles to release over the duration of one second. + **/ + void SetRate(int rate); +}; + +//implementation// + +template +void ZBaseParticleSystem::AddParticle() +{ + //empty space is always at end, function is private so no checking is needed (Emit does that) + rParticles[rCurParticles] = NewParticle(); + ++rCurParticles; +} + +template +ZBaseParticleSystem::ZBaseParticleSystem() +{ + rEngine = ZEngine::GetInstance(); + rParticles = NULL; + rMaxParticles = rCurParticles = rNumParticlesPerSec = 0; + rLastUpdate = rEngine->GetTime(); +} + +template +ZBaseParticleSystem::~ZBaseParticleSystem() +{ + if(rParticles) + delete []rParticles; +} + +template +void ZBaseParticleSystem::Emit(int numParticles) +{ + while(numParticles > 0 && rCurParticles < rMaxParticles) + { + AddParticle(); + --numParticles; + } +} + +template +void ZBaseParticleSystem::Update() +{ + float elapsed = (rEngine->GetTime()-rLastUpdate)/1000.0f; + double emitAmount; + static double overflow=0; + + //update every particle and remove dead particles + for(unsigned int i=0; i < rCurParticles; ++i) + { + UpdateParticle(i,elapsed); + if(rParticles[i].xPos < 0 || rParticles[i].xPos > rEngine->Width() + || rParticles[i].yPos < 0 || rParticles[i].yPos > rEngine->Height() || rParticles[i].energy <= 0) + { + rParticles[i] = rParticles[--rCurParticles]; + --i; //go back one to process that particle + } + } + + rLastUpdate = rEngine->GetTime(); + + emitAmount = elapsed*rNumParticlesPerSec; + overflow += emitAmount - static_cast(emitAmount); //only floating point portion of emitAmount + Emit(static_cast(emitAmount)); + if(overflow >= .95) //a little lower than one, for tolerance + { + Emit(1); + overflow = 0; //dump & clear overflow + } +} + +template +void ZBaseParticleSystem::SetMaxParticles(int max) +{ + particleType *temp; + unsigned int i; + + if(max) + { + if(max != rMaxParticles) //only do this if size changed + { + if(rCurParticles) + { + rCurParticles %= max; + //copy current particles to temp + temp = new particleType[rCurParticles]; + for(i=0; i < rCurParticles; ++i) + temp[i] = rParticles[i]; + } + + //change size of rParticles + if(rParticles) + delete []rParticles; + rParticles = new particleType[max]; + rMaxParticles = max; + + if(rCurParticles) + { + //copy particles from temp back to rParticles + for(i=0; i < rCurParticles; ++i) + rParticles[i] = temp[i]; + + delete []temp; + } + } + } + else + { + rMaxParticles = rCurParticles = 0; + if(rParticles) + delete []rParticles; + } +} + +template +void ZBaseParticleSystem::SetRate(int rate) +{ + rNumParticlesPerSec = rate; +} + +} //namespace ZE + +#endif //__ze_zbaseparticlesystem_h__ diff --git a/include/ZE_ZSimpleParticleSystem.h b/include/ZE_ZSimpleParticleSystem.h new file mode 100755 index 0000000..8b1a2c0 --- /dev/null +++ b/include/ZE_ZSimpleParticleSystem.h @@ -0,0 +1,390 @@ +/******************************************************************************* + This file is Part of the ZEngine Library for 2D game development. + Copyright (C) 2002, 2003 James Turk + + Licensed under a BSD-style license. + + The maintainer of this library is James Turk (james@conceptofzero.net) + and the home of this Library is http://www.zengine.sourceforge.net +*******************************************************************************/ + +/*! + \file ZE_ZSimpleParticleSystem.h + \brief Definition and implementation file for a simple particle system for ZEngine. + + Definition and implementation file for ZEngine simple particle system, ZSimpleParticleSystem based on ZBaseParticleSystem. + Due to problems with template classes the template implementation needs to be in the same file as the declaration. +
$id$
+ \author James Turk +**/ + +#ifndef __ze_zsimpleparticlesystem_h__ +#define __ze_zsimpleparticlesystem_h__ + +#include "ZEngine.h" + +namespace ZE +{ + +/*! + \brief Simple particle class for ZSimpleParticleSystem. + + General purpose particle, contains needed variables for a functional particle system. +**/ +class ZSimpleParticle : public ZBaseParticle +{ + public: + //! Previous X position of particle. + float xPrev; + //! Previous Y position of particle. + float yPrev; + //! X Velocity of particle per second. + float xVel; + //! Y Velocity of particle per second. + float yVel; + //! Energy change per second. + float energyDelta; + //! Size of particle. + float size; + //! Size change per second. + float sizeDelta; + //! Red component of particle color. + Uint8 r; + //! Green component of particle color. + Uint8 g; + //! Blue component of particle color. + Uint8 b; + //! Alpha component of particle color. + Uint8 a; +}; + +/*! + \brief Possible draw styles for ZSimpleParticleSystem. + + Possible draw styles for ZSimpleParticleSystem, each specifies different code with which the particles will be drawn. +**/ +enum ParticleDrawStyle +{ + DS_POINT, /*!< Draw particles as simple points. */ + DS_LINE, /*!< Draw particles as lines between the current position and the last. */ + DS_IMAGE /*!< Draw particles as an image. */ +}; + +/*! + \brief ZSimpleParticleSystem class, a simple particle system provided originally as an example. + + ZSimpleParticleSystem class, example of implementation of a particle system on top of ZBaseParticleSystem base, + designed for flexibility and ease of use over speed. More specific, therefore even less optimized for specific + circumstances. Should be concidered usable but not optimal. (Although it is a great source of code for your + own implementations.) +**/ +template +class ZSimpleParticleSystem : public ZBaseParticleSystem +{ + protected: + //! Draw style, one of the three enumerated values specifying how particles will be drawn. + ParticleDrawStyle rStyle; + //! Image to draw (only used if rStyle is DS_IMAGE). + ZImage rImage; + //! Minimum X value for starting position. + float rMinX; + //! Maximum X value for starting position. + float rMaxX; + //! Minimum Y value for starting position. + float rMinY; + //! Maximum Y value for starting position. + float rMaxY; + //! Minimum X velocity, particle moves it's velocity every second. + float rMinXVel; + //! Maximum X velocity, particle moves it's velocity every second. + float rMaxXVel; + //! Minimum Y velocity, particle moves it's velocity every second. + float rMinYVel; + //! Maximum Y velocity, particle moves it's velocity every second. + float rMaxYVel; + //! Minimum starting energy. (Remember particles with energy values <= 0 are removed.) + float rMinEnergy; + //! Maximum starting energy. + float rMaxEnergy; + //! Minimum energy change per second. + float rMinEnergyDelta; + //! Maximum energy change per second. + float rMaxEnergyDelta; + //! Minimum starting size. + float rMinSize; + //! Maximum starting size. + float rMaxSize; + //! Minimum size change per second. + float rMinSizeDelta; + //! Maximum size change per second. + float rMaxSizeDelta; + //! Minimum red component of color, 0-255. + Uint8 rMinRed; + //! Maximum red component of color, 0-255. + Uint8 rMaxRed; + //! Minimum green component of color, 0-255. + Uint8 rMinGreen; + //! Maximum green component of color, 0-255. + Uint8 rMaxGreen; + //! Minimum blue component of color, 0-255. + Uint8 rMinBlue; + //! Maximum blue component of color, 0-255. + Uint8 rMaxBlue; + //! Minimum alpha of particle, 0-255. + Uint8 rMinAlpha; + //! Maximum alpha of particle, 0-255. + Uint8 rMaxAlpha; + + /*! + \brief Function which creates a new particle. + + Implementation of pure virtual NewParticle from ZBaseParticleSystem, creates a new particle with + it's members set to values between their min and max value as set by the system. + **/ + virtual particleType NewParticle(); + + /*! + \brief Updates a given particle given it's index and the elapsedTime. + + Implementation of pure virtual UpdateParticle from ZBaseParticleSystem, updates a given particle + relative to the elapsed time. + \param index Index of particle in rParticles array to update. + \param elapsedTime Decimal portion of a second since last call. + **/ + virtual void UpdateParticle(int index, float elapsedTime); + + public: + /*! + \brief Draws all particles. + + Implementation of pure virtual Render from ZBaseParticleSystem, draws all particles in specified + ParticleDrawStyle. + **/ + virtual void Render(); + + /*! + \brief Sets ParticleDrawStyle for this system. + + Sets the method of drawing particles, point, line, or image particles. + \param style ParticleDrawStyle for this particle system to use. + **/ + void SetDrawStyle(ParticleDrawStyle style); + + /*! + \brief Sets image for particle system. + + Sets image for particle system to use, assuming the drawing style is DS_IMAGE. + \brief filename Filename of image to load for the system. + **/ + void SetImage(std::string filename); + + /*! + \brief Sets the range of initial positions. + + Sets the range of initial positions for a new particle. + \param minX Minimum X coordinate for new particles. + \param minY Minimum Y coordinate for new particles. + \param maxX Maximum X coordinate for new particles. + \param maxY Maximum Y coordinate for new particles. + **/ + void SetPosRange(float minX, float minY, float maxX, float maxY); + + /*! + \brief Sets range of velocities for particles. + + Sets range from which a new particle obtains it's random velocity, + \param minXVel Minimum X velocity of a particle. + \param minYVel Minimum Y velocity of a particle. + \param maxXVel Maximum X velocity of a particle. + \param maxYVel Maximum Y velocity of a particle. + **/ + void SetVelocityRange(float minXVel, float minYVel, float maxXVel, float maxYVel); + + /*! + \brief Sets range of initial energy and energyDelta. + + Sets the possible ranges for a particles starting energy and it's energyDelta. Particles with + energy less than or equal to 0 are deleted by ZBaseParticleSystem::Update. + \param minEnergy Minimum initial energy. + \param maxEnergy Maximum initial energy. + \param minEnergyDelta Minimum energy delta. + \param maxEnergyDelta Maximum energy delta. + **/ + void SetEnergyRange(float minEnergy, float maxEnergy, float minEnergyDelta=0, float maxEnergyDelta=0); + + /*! + \brief Sets range of initial size and sizeDelta. + + Sets the possible ranges for a particles starting size and it's sizeDelta. + \param minSize Minimum initial size. + \param maxSize Maximum initial size. + \param minSizeDelta Minimum size delta. + \param maxSizeDelta Maximum size delta. + **/ + void SetSizeRange(float minSize, float maxSize, float minSizeDelta=0, float maxSizeDelta=0); + + /*! + \brief Set range of color for a new particle. + + Sets range of possible colors, by component, for a new particle. + \param minRed Minimum value of red component (0-255). + \param maxRed Minimum value of red component (0-255). + \param minGreen Minimum value of green component (0-255). + \param maxGreen Minimum value of green component (0-255). + \param minBlue Minimum value of blue component (0-255). + \param maxBlue Minimum value of blue component (0-255). + \param minAlpha Minimum value of alpha value (0-255). + \param maxAlpha Minimum value of alpha value (0-255). + **/ + void SetColorRange(Uint8 minRed, Uint8 maxRed, Uint8 minGreen, Uint8 maxGreen, + Uint8 minBlue, Uint8 maxBlue, Uint8 minAlpha, Uint8 maxAlpha); +}; + +//implementation// + +template +particleType ZSimpleParticleSystem::NewParticle() +{ + particleType p; + + p.xPrev = p.xPos = rEngine->Rand(rMinX,rMaxX); + p.yPrev = p.yPos = rEngine->Rand(rMinY,rMaxY); + p.xVel = rEngine->Rand(rMinXVel,rMaxXVel); + p.yVel = rEngine->Rand(rMinYVel,rMaxYVel); + p.energy = rEngine->Rand(rMinEnergy,rMaxEnergy); + p.energyDelta = rEngine->Rand(rMinEnergyDelta,rMaxEnergyDelta); + p.size = rEngine->Rand(rMinSize,rMaxSize); + p.sizeDelta = rEngine->Rand(rMinSizeDelta,rMaxSizeDelta); + p.r = rEngine->Rand(rMinRed,rMaxRed); + p.g = rEngine->Rand(rMinGreen,rMaxGreen); + p.b = rEngine->Rand(rMinBlue,rMaxBlue); + p.a = rEngine->Rand(rMinAlpha,rMaxAlpha); + + return p; +} + +template +void ZSimpleParticleSystem::UpdateParticle(int index, float elapsedTime) +{ + rParticles[index].xPrev = rParticles[index].xPos; + rParticles[index].yPrev = rParticles[index].yPos; + rParticles[index].xPos += rParticles[index].xVel*elapsedTime; + rParticles[index].yPos += rParticles[index].yVel*elapsedTime; + rParticles[index].size += rParticles[index].sizeDelta*elapsedTime; + rParticles[index].energy += rParticles[index].energyDelta*elapsedTime; +} + +template +void ZSimpleParticleSystem::Render() +{ + switch(rStyle) + { + case DS_POINT: + glBindTexture(GL_TEXTURE_2D,0); + for(unsigned int i=0; i < rCurParticles; i++) + { + glPointSize(rParticles[i].size); + glBegin(GL_POINTS); + glColor4ub(rParticles[i].r,rParticles[i].g,rParticles[i].b,rParticles[i].a); + glVertex2f(rParticles[i].xPos,rParticles[i].yPos); + glEnd(); + } + break; + case DS_LINE: + glBindTexture(GL_TEXTURE_2D,0); + for(unsigned int i=0; i < rCurParticles; i++) + { + glLineWidth(rParticles[i].size); + glBegin(GL_LINES); + glColor4ub(rParticles[i].r,rParticles[i].g,rParticles[i].b,rParticles[i].a); + glVertex2f(rParticles[i].xPos,rParticles[i].yPos); + glVertex2f(rParticles[i].xPrev,rParticles[i].yPrev); + glEnd(); + } + break; + case DS_IMAGE: + float x,y,size; + rImage.Bind(); + glBegin(GL_QUADS); + for(unsigned int i=0; i < rCurParticles; i++) + { + x = rParticles[i].xPos; + y = rParticles[i].yPos; + size = rParticles[i].size; + + glColor4ub(rParticles[i].r,rParticles[i].g,rParticles[i].b,rParticles[i].a); + glTexCoord2f(0,1); glVertex2f(x,y); + glTexCoord2f(1,1); glVertex2f(x+size,y); + glTexCoord2f(0,1); glVertex2f(x+size,y-size); + glTexCoord2f(0,0); glVertex2f(x,y-size); + } + glEnd(); + break; + } +} + +template +void ZSimpleParticleSystem::SetDrawStyle(ParticleDrawStyle style) +{ + rStyle = style; +} + +template +void ZSimpleParticleSystem::SetImage(std::string filename) +{ + rImage.Open(filename); +} + +template +void ZSimpleParticleSystem::SetPosRange(float minX, float minY, float maxX, float maxY) +{ + rMinX = minX; + rMaxX = maxX; + rMinY = minY; + rMaxY = maxY; +} + +template +void ZSimpleParticleSystem::SetVelocityRange(float minXVel, float minYVel, float maxXVel, float maxYVel) +{ + rMinXVel = minXVel; + rMaxXVel = maxXVel; + rMinYVel = minYVel; + rMaxYVel = maxYVel; +} + +template +void ZSimpleParticleSystem::SetEnergyRange(float minEnergy, float maxEnergy, float minEnergyDelta, float maxEnergyDelta) +{ + rMinEnergy = minEnergy; + rMaxEnergy = maxEnergy; + rMinEnergyDelta = minEnergyDelta; + rMaxEnergyDelta = maxEnergyDelta; +} + +template +void ZSimpleParticleSystem::SetSizeRange(float minSize, float maxSize, float minSizeDelta, float maxSizeDelta) +{ + rMinSize = minSize; + rMaxSize = maxSize; + rMinSizeDelta = minSizeDelta; + rMaxSizeDelta = maxSizeDelta; +} + +template +void ZSimpleParticleSystem::SetColorRange(Uint8 minRed, Uint8 maxRed, Uint8 minGreen, Uint8 maxGreen, + Uint8 minBlue, Uint8 maxBlue, Uint8 minAlpha, Uint8 maxAlpha) +{ + rMinRed = minRed; + rMaxRed = maxRed; + rMinGreen = minGreen; + rMaxGreen = maxGreen; + rMinBlue = minBlue; + rMaxBlue = maxBlue; + rMinAlpha = minAlpha; + rMaxAlpha = maxAlpha; +} + +} //namespace ZE + +#endif //__ze_zsimpleparticlesystem_h__ diff --git a/include/ZEngine.h b/include/ZEngine.h index 426e5c9..fb50486 100644 --- a/include/ZEngine.h +++ b/include/ZEngine.h @@ -4,7 +4,7 @@ Header file for ZEngine Game Engine from Concept of Zero, this is the file that programs that wish to utilize ZEngine should include. -
$Id: ZEngine.h,v 1.26 2003/05/13 01:30:51 cozman Exp $
+
$Id: ZEngine.h,v 1.27 2003/07/10 19:19:19 cozman Exp $
\author James Turk **/ @@ -27,7 +27,7 @@ to have no leaks.
    -The ZEngine website : http://zengine.sourceforge.net/.
    -The ZEngine tutorials : http://conceptofzero.net/tutorials/zengine/.
-     -The ZEngine forums : http://www.conceptofzero.net/forums/index.php?act=SF&f=15 +     -The ZEngine forums : http://www.conceptofzero.net/index.php?name=PNphpBB2&file=viewforum&f=4 \section Licensing Licensing
@@ -57,6 +57,9 @@ #include "ZE_ZTimer.h" #include "ZE_ZConfigFile.h" #include "ZE_ZRect.h" +#include "ZE_ZRandGen.h" +#include "ZE_ZBaseParticleSystem.h" +#include "ZE_ZSimpleParticleSystem.h" #ifdef USE_SDL_TTF #include "ZE_ZFont.h" #endif