Particle System

This commit is contained in:
James Turk 2003-07-10 19:19:19 +00:00
parent b544487854
commit bd9e5917df
3 changed files with 671 additions and 2 deletions

276
include/ZE_ZBaseParticleSystem.h Executable file
View File

@ -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.
<br>$id$<br>
\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 particleType>
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 <class particleType>
void ZBaseParticleSystem<particleType>::AddParticle()
{
//empty space is always at end, function is private so no checking is needed (Emit does that)
rParticles[rCurParticles] = NewParticle();
++rCurParticles;
}
template <class particleType>
ZBaseParticleSystem<particleType>::ZBaseParticleSystem()
{
rEngine = ZEngine::GetInstance();
rParticles = NULL;
rMaxParticles = rCurParticles = rNumParticlesPerSec = 0;
rLastUpdate = rEngine->GetTime();
}
template <class particleType>
ZBaseParticleSystem<particleType>::~ZBaseParticleSystem()
{
if(rParticles)
delete []rParticles;
}
template <class particleType>
void ZBaseParticleSystem<particleType>::Emit(int numParticles)
{
while(numParticles > 0 && rCurParticles < rMaxParticles)
{
AddParticle();
--numParticles;
}
}
template <class particleType>
void ZBaseParticleSystem<particleType>::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<int>(emitAmount); //only floating point portion of emitAmount
Emit(static_cast<int>(emitAmount));
if(overflow >= .95) //a little lower than one, for tolerance
{
Emit(1);
overflow = 0; //dump & clear overflow
}
}
template <class particleType>
void ZBaseParticleSystem<particleType>::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 <class particleType>
void ZBaseParticleSystem<particleType>::SetRate(int rate)
{
rNumParticlesPerSec = rate;
}
} //namespace ZE
#endif //__ze_zbaseparticlesystem_h__

View File

@ -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.
<br>$id$<br>
\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 particleType>
class ZSimpleParticleSystem : public ZBaseParticleSystem<particleType>
{
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 <class particleType>
particleType ZSimpleParticleSystem<particleType>::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 <class particleType>
void ZSimpleParticleSystem<particleType>::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 <class particleType>
void ZSimpleParticleSystem<particleType>::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 <class particleType>
void ZSimpleParticleSystem<particleType>::SetDrawStyle(ParticleDrawStyle style)
{
rStyle = style;
}
template <class particleType>
void ZSimpleParticleSystem<particleType>::SetImage(std::string filename)
{
rImage.Open(filename);
}
template <class particleType>
void ZSimpleParticleSystem<particleType>::SetPosRange(float minX, float minY, float maxX, float maxY)
{
rMinX = minX;
rMaxX = maxX;
rMinY = minY;
rMaxY = maxY;
}
template <class particleType>
void ZSimpleParticleSystem<particleType>::SetVelocityRange(float minXVel, float minYVel, float maxXVel, float maxYVel)
{
rMinXVel = minXVel;
rMaxXVel = maxXVel;
rMinYVel = minYVel;
rMaxYVel = maxYVel;
}
template <class particleType>
void ZSimpleParticleSystem<particleType>::SetEnergyRange(float minEnergy, float maxEnergy, float minEnergyDelta, float maxEnergyDelta)
{
rMinEnergy = minEnergy;
rMaxEnergy = maxEnergy;
rMinEnergyDelta = minEnergyDelta;
rMaxEnergyDelta = maxEnergyDelta;
}
template <class particleType>
void ZSimpleParticleSystem<particleType>::SetSizeRange(float minSize, float maxSize, float minSizeDelta, float maxSizeDelta)
{
rMinSize = minSize;
rMaxSize = maxSize;
rMinSizeDelta = minSizeDelta;
rMaxSizeDelta = maxSizeDelta;
}
template <class particleType>
void ZSimpleParticleSystem<particleType>::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__

View File

@ -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.
<br>$Id: ZEngine.h,v 1.26 2003/05/13 01:30:51 cozman Exp $<br>
<br>$Id: ZEngine.h,v 1.27 2003/07/10 19:19:19 cozman Exp $<br>
\author James Turk
**/
@ -27,7 +27,7 @@
to have no leaks.<br>
&nbsp;&nbsp;&nbsp;&nbsp;-The ZEngine website : http://zengine.sourceforge.net/.<br>
&nbsp;&nbsp;&nbsp;&nbsp;-The ZEngine tutorials : http://conceptofzero.net/tutorials/zengine/.<br>
&nbsp;&nbsp;&nbsp;&nbsp;-The ZEngine forums : http://www.conceptofzero.net/forums/index.php?act=SF&f=15
&nbsp;&nbsp;&nbsp;&nbsp;-The ZEngine forums : http://www.conceptofzero.net/index.php?name=PNphpBB2&file=viewforum&f=4
\section Licensing Licensing
<br>
@ -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