Browse Source

Reintegrated ParticleSystem.

rude 16 years ago
parent
commit
a3bff7cde9

+ 44 - 12
platform/msvc2008/graphics/graphics.vcproj

@@ -172,6 +172,18 @@
 		<Filter
 		<Filter
 			Name="opengl"
 			Name="opengl"
 			>
 			>
+			<File
+				RelativePath="..\..\..\src\modules\graphics\Drawable.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						ObjectFile="$(IntDir)\graphics\"
+					/>
+				</FileConfiguration>
+			</File>
 			<File
 			<File
 				RelativePath="..\..\..\src\modules\graphics\opengl\Font.cpp"
 				RelativePath="..\..\..\src\modules\graphics\opengl\Font.cpp"
 				>
 				>
@@ -269,6 +281,22 @@
 				RelativePath="..\..\..\src\modules\graphics\opengl\ImageFont.h"
 				RelativePath="..\..\..\src\modules\graphics\opengl\ImageFont.h"
 				>
 				>
 			</File>
 			</File>
+			<File
+				RelativePath="..\..\..\src\modules\graphics\opengl\ParticleSystem.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						ObjectFile="$(IntDir)\graphics\opengl\"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="..\..\..\src\modules\graphics\opengl\ParticleSystem.h"
+				>
+			</File>
 			<File
 			<File
 				RelativePath="..\..\..\src\modules\graphics\opengl\Quad.cpp"
 				RelativePath="..\..\..\src\modules\graphics\opengl\Quad.cpp"
 				>
 				>
@@ -373,6 +401,22 @@
 				RelativePath="..\..\..\src\modules\graphics\opengl\wrap_Image.h"
 				RelativePath="..\..\..\src\modules\graphics\opengl\wrap_Image.h"
 				>
 				>
 			</File>
 			</File>
+			<File
+				RelativePath="..\..\..\src\modules\graphics\opengl\wrap_ParticleSystem.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						ObjectFile="$(IntDir)\graphics\opengl\"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath="..\..\..\src\modules\graphics\opengl\wrap_ParticleSystem.h"
+				>
+			</File>
 			<File
 			<File
 				RelativePath="..\..\..\src\modules\graphics\opengl\wrap_Quad.cpp"
 				RelativePath="..\..\..\src\modules\graphics\opengl\wrap_Quad.cpp"
 				>
 				>
@@ -398,18 +442,6 @@
 				>
 				>
 			</File>
 			</File>
 		</Filter>
 		</Filter>
-		<File
-			RelativePath="..\..\..\src\modules\graphics\Drawable.cpp"
-			>
-			<FileConfiguration
-				Name="Debug|Win32"
-				>
-				<Tool
-					Name="VCCLCompilerTool"
-					ObjectFile="$(IntDir)\graphics\"
-				/>
-			</FileConfiguration>
-		</File>
 		<File
 		<File
 			RelativePath="..\..\..\src\modules\graphics\Drawable.h"
 			RelativePath="..\..\..\src\modules\graphics\Drawable.h"
 			>
 			>

+ 32 - 0
platform/msvc2008/love.vcproj

@@ -925,6 +925,22 @@
 						RelativePath="..\..\src\modules\graphics\opengl\ImageFont.h"
 						RelativePath="..\..\src\modules\graphics\opengl\ImageFont.h"
 						>
 						>
 					</File>
 					</File>
+					<File
+						RelativePath="..\..\src\modules\graphics\opengl\ParticleSystem.cpp"
+						>
+						<FileConfiguration
+							Name="Debug|Win32"
+							>
+							<Tool
+								Name="VCCLCompilerTool"
+								ObjectFile="$(IntDir)\graphics\opengl\"
+							/>
+						</FileConfiguration>
+					</File>
+					<File
+						RelativePath="..\..\src\modules\graphics\opengl\ParticleSystem.h"
+						>
+					</File>
 					<File
 					<File
 						RelativePath="..\..\src\modules\graphics\opengl\Quad.cpp"
 						RelativePath="..\..\src\modules\graphics\opengl\Quad.cpp"
 						>
 						>
@@ -1045,6 +1061,22 @@
 						RelativePath="..\..\src\modules\graphics\opengl\wrap_Image.h"
 						RelativePath="..\..\src\modules\graphics\opengl\wrap_Image.h"
 						>
 						>
 					</File>
 					</File>
+					<File
+						RelativePath="..\..\src\modules\graphics\opengl\wrap_ParticleSystem.cpp"
+						>
+						<FileConfiguration
+							Name="Debug|Win32"
+							>
+							<Tool
+								Name="VCCLCompilerTool"
+								ObjectFile="$(IntDir)\graphics\opengl\"
+							/>
+						</FileConfiguration>
+					</File>
+					<File
+						RelativePath="..\..\src\modules\graphics\opengl\wrap_ParticleSystem.h"
+						>
+					</File>
 					<File
 					<File
 						RelativePath="..\..\src\modules\graphics\opengl\wrap_Quad.cpp"
 						RelativePath="..\..\src\modules\graphics\opengl\wrap_Quad.cpp"
 						>
 						>

+ 498 - 0
src/modules/graphics/opengl/ParticleSystem.cpp

@@ -0,0 +1,498 @@
+/**
+* Copyright (c) 2006-2009 LOVE Development Team
+* 
+* This software is provided 'as-is', without any express or implied
+* warranty.  In no event will the authors be held liable for any damages
+* arising from the use of this software.
+* 
+* Permission is granted to anyone to use this software for any purpose,
+* including commercial applications, and to alter it and redistribute it
+* freely, subject to the following restrictions:
+* 
+* 1. The origin of this software must not be misrepresented; you must not
+*    claim that you wrote the original software. If you use this software
+*    in a product, an acknowledgment in the product documentation would be
+*    appreciated but is not required.
+* 2. Altered source versions must be plainly marked as such, and must not be
+*    misrepresented as being the original software.
+* 3. This notice may not be removed or altered from any source distribution.
+**/
+
+#include "ParticleSystem.h"
+
+#include <SDL_opengl.h>
+#include <cmath>
+#include <cstdlib>
+#include <cstring>
+
+namespace love
+{
+namespace graphics
+{
+namespace opengl
+{
+
+	float calculate_variation(float inner, float outer, float var)
+	{
+		float low = inner - (outer/2.0f)*var;
+		float high = inner + (outer/2.0f)*var;
+		float r = (rand() / (float(RAND_MAX)+1));
+		return low*(1-r)+high*r;
+	}
+
+
+	ParticleSystem::ParticleSystem(Image * sprite, unsigned int buffer) : pStart(0), pLast(0), pEnd(0), active(true), emissionRate(0),
+															emitCounter(0), lifetime(-1), life(0), particleLifeMin(0), particleLifeMax(0),
+															direction(0), spread(0), relative(false), speedMin(0), speedMax(0), gravityMin(0),
+															gravityMax(0), radialAccelerationMin(0), radialAccelerationMax(0),
+															tangentialAccelerationMin(0), tangentialAccelerationMax(0),
+															sizeStart(1), sizeEnd(1), sizeVariation(0), rotationMin(0), rotationMax(0),
+															spinStart(0), spinEnd(0), spinVariation(0)
+	{	
+		this->sprite = sprite;
+		sprite->retain();
+		memset(colorStart, 255, 4);
+		memset(colorEnd, 255, 4);
+		setBufferSize(buffer);
+	}
+
+	ParticleSystem::~ParticleSystem()
+	{
+		if(this->sprite != 0)
+		{
+			this->sprite->release();
+			this->sprite = 0;
+		}
+
+		if(pStart != 0)
+			delete [] pStart;
+	}
+
+	void ParticleSystem::add()
+	{
+		if(isFull()) return;
+		
+		float min,max;
+
+		min = particleLifeMin;
+		max = particleLifeMax;
+		if(min == max)
+			pLast->life = min;
+		else
+			pLast->life = (rand() / (float(RAND_MAX)+1)) * (max - min) + min;
+		pLast->lifetime = pLast->life;
+
+		pLast->position[0] = position.getX();
+		pLast->position[1] = position.getY();
+
+		min = direction - spread/2.0f;
+		max = direction + spread/2.0f;
+		pLast->direction = (rand() / (float(RAND_MAX)+1)) * (max - min) + min;
+
+		min = speedMin;
+		max = speedMax;
+		float speed = (rand() / (float(RAND_MAX)+1)) * (max - min) + min;
+		pLast->speed = love::Vector(cos(pLast->direction), sin(pLast->direction));
+		pLast->speed *= speed;
+
+		min = gravityMin;
+		max = gravityMax;
+		pLast->gravity = (rand() / (float(RAND_MAX)+1)) * (max - min) + min;
+
+		min = radialAccelerationMin;
+		max = radialAccelerationMax;
+		pLast->radialAcceleration = (rand() / (float(RAND_MAX)+1)) * (max - min) + min;
+
+		min = tangentialAccelerationMin;
+		max = tangentialAccelerationMax;
+		pLast->tangentialAcceleration = (rand() / (float(RAND_MAX)+1)) * (max - min) + min;
+
+		pLast->sizeStart = calculate_variation(sizeStart, sizeEnd, sizeVariation);
+		pLast->sizeEnd = calculate_variation(sizeEnd, sizeStart, sizeVariation);
+		pLast->size = pLast->sizeStart;
+
+		min = rotationMin;
+		max = rotationMax;
+		pLast->spinStart = calculate_variation(spinStart, spinEnd, spinVariation);
+		pLast->spinEnd = calculate_variation(spinEnd, spinStart, spinVariation);
+		pLast->rotation = (rand() / (float(RAND_MAX)+1)) * (max - min) + min;;
+
+		pLast->color[0] = (float)colorStart[0] / 255;
+		pLast->color[1] = (float)colorStart[1] / 255;
+		pLast->color[2] = (float)colorStart[2] / 255;
+		pLast->color[3] = (float)colorStart[3] / 255;
+			
+		pLast++;
+	}
+
+	void ParticleSystem::remove(particle * p)
+	{
+		if(!isEmpty())
+		{
+			*p = *(--pLast);
+		}
+	}
+
+	void ParticleSystem::setSprite(Image * image)
+	{
+		if(this->sprite != 0)
+		{
+			this->sprite->release();
+			this->sprite = 0;
+		}
+
+		this->sprite = image;
+	}
+
+	void ParticleSystem::setBufferSize(unsigned int size)
+	{
+		// delete previous data
+		delete [] pStart;
+
+		pLast = pStart = new particle[size];
+
+		pEnd = pStart + size;
+	}
+
+	void ParticleSystem::setEmissionRate(int rate)
+	{
+		emissionRate = rate;
+	}
+
+	void ParticleSystem::setLifetime(float life)
+	{
+		this->life = lifetime = life;
+	}
+
+	void ParticleSystem::setParticleLife(float min, float max)
+	{
+		particleLifeMin = min;
+		if(max == 0)
+			particleLifeMax = min;
+		else
+			particleLifeMax = max;
+	}
+
+	void ParticleSystem::setPosition(float x, float y)
+	{
+		position = love::Vector(x, y);
+	}
+
+	void ParticleSystem::setDirection(float direction)
+	{
+		this->direction = direction * LOVE_M_TORAD;
+	}
+
+	void ParticleSystem::setSpread(float spread)
+	{
+		this->spread = spread * LOVE_M_TORAD;
+	}
+
+	void ParticleSystem::setRelativeDirection(bool relative)
+	{
+		this->relative = relative;
+	}
+
+	void ParticleSystem::setSpeed(float speed)
+	{
+		speedMin = speedMax = speed;
+	}
+
+	void ParticleSystem::setSpeed(float min, float max)
+	{
+		speedMin = min;
+		speedMax = max;
+	}
+
+	void ParticleSystem::setGravity(float gravity)
+	{
+		gravityMin = gravityMax = gravity;
+	}
+
+	void ParticleSystem::setGravity(float min, float max)
+	{
+		gravityMin = min;
+		gravityMax = max;
+	}
+
+	void ParticleSystem::setRadialAcceleration(float acceleration)
+	{
+		radialAccelerationMin = radialAccelerationMax = acceleration;
+	}
+
+	void ParticleSystem::setRadialAcceleration(float min, float max)
+	{
+		radialAccelerationMin = min;
+		radialAccelerationMax = max;
+	}
+
+	void ParticleSystem::setTangentialAcceleration(float acceleration)
+	{
+		tangentialAccelerationMin = tangentialAccelerationMax = acceleration;
+	}
+
+	void ParticleSystem::setTangentialAcceleration(float min, float max)
+	{
+		tangentialAccelerationMin = min;
+		tangentialAccelerationMax = max;
+	}
+
+	void ParticleSystem::setSize(float size)
+	{
+		sizeStart = size;
+		sizeEnd = size;
+	}
+
+	void ParticleSystem::setSize(float start, float end)
+	{
+		sizeStart = start;
+		sizeEnd = end;
+	}
+
+	void ParticleSystem::setSize(float start, float end, float variation)
+	{
+		sizeStart = start;
+		sizeEnd = end;
+		sizeVariation = variation;
+	}
+
+	void ParticleSystem::setSizeVariation(float variation)
+	{
+		sizeVariation = variation;
+	}
+
+	void ParticleSystem::setRotation(float rotation)
+	{
+		rotationMin = rotationMax = rotation;
+	}
+
+	void ParticleSystem::setRotation(float min, float max)
+	{
+		rotationMin = min;
+		rotationMax = max;
+	}
+
+	void ParticleSystem::setSpin(float spin)
+	{
+		spinStart = spin * LOVE_M_TORAD;
+		spinEnd = spin * LOVE_M_TORAD;
+	}
+
+	void ParticleSystem::setSpin(float start, float end)
+	{
+		spinStart = start * LOVE_M_TORAD;
+		spinEnd = end * LOVE_M_TORAD;
+	}
+
+	void ParticleSystem::setSpin(float start, float end, float variation)
+	{
+		spinStart = start * LOVE_M_TORAD;
+		spinEnd = end * LOVE_M_TORAD;
+		spinVariation = variation * LOVE_M_TORAD;
+	}
+
+	void ParticleSystem::setSpinVariation(float variation)
+	{
+		spinVariation = variation * LOVE_M_TORAD;
+	}
+
+	void ParticleSystem::setColor(unsigned char * color)
+	{
+		memcpy(colorStart, color, 4);
+		memcpy(colorEnd, color, 4);
+	}
+
+	void ParticleSystem::setColor(unsigned char * start, unsigned char * end)
+	{
+		memcpy(colorStart, start, 4);
+		memcpy(colorEnd, end, 4);
+	}
+
+	float ParticleSystem::getX() const
+	{
+		return position.getX();
+	}
+
+	float ParticleSystem::getY() const
+	{
+		return position.getY();
+	}
+
+	float ParticleSystem::getDirection() const
+	{
+		return direction * LOVE_M_TODEG;
+	}
+
+	float ParticleSystem::getSpread() const
+	{
+		return spread * LOVE_M_TODEG;
+	}
+
+	int ParticleSystem::count() const
+	{
+		return (int)(pLast - pStart);
+	}
+
+	void ParticleSystem::start()
+	{
+		active = true;
+	}
+
+	void ParticleSystem::stop()
+	{
+		active = false;
+		life = lifetime;
+		emitCounter = 0;
+	}
+
+	void ParticleSystem::pause()
+	{
+		active = false;
+	}
+
+	void ParticleSystem::reset()
+	{
+		pLast = pStart;
+		life = lifetime;
+		emitCounter = 0;
+	}
+
+	bool ParticleSystem::isActive() const
+	{
+		return active;
+	}
+
+	bool ParticleSystem::isEmpty() const
+	{
+		return pStart == pLast;
+	}
+
+	bool ParticleSystem::isFull() const
+	{
+		return pLast == pEnd;
+	}
+
+	void ParticleSystem::draw(float x, float y, float angle, float sx, float sy, float ox, float oy) const
+	{
+		if(sprite == 0) return; // just in case of failure
+
+		glPushMatrix();
+		glPushAttrib(GL_CURRENT_BIT);
+
+		glTranslatef(x, y, 0);
+		glRotatef(angle, 0, 0, 1.0f);
+		glScalef(sx, sy, 1.0f);
+		glTranslatef( ox, oy, 0);
+
+		particle * p = pStart;
+		while(p != pLast)
+		{
+			glPushMatrix();
+
+			glColor4f(p->color[0],p->color[1],p->color[2],p->color[3]);
+			glTranslatef(p->position[0],p->position[1],0.0f);
+			glRotatef(p->rotation * 57.29578f, 0.0f, 0.0f, 1.0f); // rad * (180 / pi)
+			glScalef(p->size,p->size,1.0f);
+			sprite->draw(0,0, 0, 1, 1, 0, 0);
+
+			glPopMatrix();
+			p++;
+		}
+
+		glPopAttrib();
+		glPopMatrix();
+	}
+
+	void ParticleSystem::update(float dt)
+	{
+		// Traverse all particles and update.
+		particle * p = pStart;
+
+		// Make some more particles.
+		if(active)
+		{
+			float rate = 1.0f / emissionRate; // the amount of time between each particle emit
+			emitCounter += dt;
+			while(emitCounter > rate)
+			{
+				add();
+				emitCounter -= rate;
+			}
+			/*int particles = (int)(emissionRate * dt);
+			for(int i = 0; i != particles; i++)
+				add();*/
+
+			life -= dt;
+			if(lifetime != -1 && life < 0)
+				stop();
+		}
+
+		while(p != pLast)
+		{
+			// Decrease lifespan.
+			p->life -= dt;
+
+			if(p->life > 0)
+			{
+
+				// Temp variables.
+				love::Vector radial, tangential, gravity(0, p->gravity);
+				love::Vector ppos(p->position[0], p->position[1]);
+
+				// Get vector from particle center to particle.
+				radial = ppos - position;
+				radial.normalize();
+				tangential = radial;
+
+				// Resize radial acceleration.
+				radial *= p->radialAcceleration;
+
+				// Calculate tangential acceleration.
+				{
+					float a = tangential.getX();
+					tangential.setX(-tangential.getY());
+					tangential.setY(a);
+				}
+
+				// Resize tangential.
+				tangential *= p->tangentialAcceleration;
+
+				// Update position.
+				p->speed += (radial+tangential+gravity)*dt;
+
+				// Modify position.
+				ppos += p->speed * dt;
+
+				p->position[0] = ppos.getX();
+				p->position[1] = ppos.getY();
+
+				const float t = p->life / p->lifetime;
+
+				// Change size.
+				p->size = p->sizeEnd - ((p->sizeEnd - p->sizeStart) * t);
+
+				// Rotate.
+				p->rotation += (p->spinStart*(1-t) + p->spinEnd*t)*dt;
+
+				// Update color.
+				p->color[0] = (float)(colorEnd[0]*(1.0f-t) + colorStart[0] * t)/255.0f;
+				p->color[1] = (float)(colorEnd[1]*(1.0f-t) + colorStart[1] * t)/255.0f;
+				p->color[2] = (float)(colorEnd[2]*(1.0f-t) + colorStart[2] * t)/255.0f;
+				p->color[3] = (float)(colorEnd[3]*(1.0f-t) + colorStart[3] * t)/255.0f;
+	
+				// Next particle.
+				p++;
+			}
+			else
+			{
+				remove(p);
+
+				if(p >= pLast)
+					return;
+			} // else
+		} // while
+	}
+
+} // opengl
+} // graphics
+} // love

+ 429 - 0
src/modules/graphics/opengl/ParticleSystem.h

@@ -0,0 +1,429 @@
+/**
+* Copyright (c) 2006-2009 LOVE Development Team
+* 
+* This software is provided 'as-is', without any express or implied
+* warranty.  In no event will the authors be held liable for any damages
+* arising from the use of this software.
+* 
+* Permission is granted to anyone to use this software for any purpose,
+* including commercial applications, and to alter it and redistribute it
+* freely, subject to the following restrictions:
+* 
+* 1. The origin of this software must not be misrepresented; you must not
+*    claim that you wrote the original software. If you use this software
+*    in a product, an acknowledgment in the product documentation would be
+*    appreciated but is not required.
+* 2. Altered source versions must be plainly marked as such, and must not be
+*    misrepresented as being the original software.
+* 3. This notice may not be removed or altered from any source distribution.
+**/
+
+#ifndef LOVE_GRAPHICS_OPENGL_PARTICLE_SYSTEM_H
+#define LOVE_GRAPHICS_OPENGL_PARTICLE_SYSTEM_H
+
+// LOVE
+
+#include <common/math.h>
+#include <common/Vector.h>
+#include <graphics/Drawable.h>
+#include "Image.h"
+
+namespace love
+{
+namespace graphics
+{
+namespace opengl
+{
+
+	// Represents a single particle.
+	struct particle
+	{
+		float lifetime;
+		float life;
+
+		float position[2];
+		float direction;
+
+		love::Vector speed;
+		float gravity;
+		float radialAcceleration;
+		float tangentialAcceleration;
+
+		float size;
+		float sizeStart;
+		float sizeEnd;
+
+		float rotation;
+		float spinStart;
+		float spinEnd;
+
+		float color[4];
+	};
+
+	/**
+	* A class for creating, moving and drawing particles.
+	* A big thanks to bobthebloke.org
+	**/
+	class ParticleSystem : public Drawable
+	{
+	protected:
+
+		// The max amount of particles.
+		unsigned int bufferSize;
+
+		// Pointer to the first particle.
+		particle * pStart;
+
+		// Pointer to the next available free space.
+		particle * pLast;
+
+		// Pointer to the end of the memory allocation.
+		particle * pEnd;
+
+		// The sprite to be drawn.
+		Image * sprite;
+
+		// Whether the particle emitter is active.
+		bool active;
+
+		// The emission rate (particles/sec).
+		int emissionRate;
+
+		// Used to determine when a particle should be emitted.
+		float emitCounter;
+
+		// The relative position of the particle emitter.
+		love::Vector position;
+
+		// The lifetime of the particle emitter (-1 means infinite) and the life it has left.
+		float lifetime;
+		float life;
+
+		// The particle life.
+		float particleLifeMin;
+		float particleLifeMax;
+
+		// The direction (and spread) the particles will be emitted in. Measured in radians.
+		float direction;
+		float spread;
+
+		// Whether the direction should be relative to the emitter's movement.
+		bool relative;
+
+		// The speed.
+		float speedMin;
+		float speedMax;
+
+		// Acceleration towards the bottom of the screen
+		float gravityMin;
+		float gravityMax;
+
+		// Acceleration towards the emitter's center
+		float radialAccelerationMin;
+		float radialAccelerationMax;
+
+		// Acceleration perpendicular to the particle's direction.
+		float tangentialAccelerationMin;
+		float tangentialAccelerationMax;
+
+		// Size.
+		float sizeStart;
+		float sizeEnd;
+		float sizeVariation;
+
+		// Rotation
+		float rotationMin;
+		float rotationMax;
+
+		// Spin.
+		float spinStart;
+		float spinEnd;
+		float spinVariation;
+
+		// Color.
+		unsigned char colorStart[4];
+		unsigned char colorEnd[4];
+
+		void add();
+		void remove(particle * p);
+
+	public:
+
+		/**
+		* Creates a particle system with the specified buffersize and sprite.
+		**/
+		ParticleSystem(Image * sprite, unsigned int buffer);
+
+		/**
+		* Deletes any allocated memory.
+		**/
+		virtual ~ParticleSystem();
+
+		/**
+		* Sets the sprite used in the particle system.
+		* @param sprite The new sprite.
+		**/
+		void setSprite(Image * image);
+
+		/**
+		* Clears the current buffer and allocates the appropriate amount of space for the buffer.
+		* @param size The new buffer size.
+		**/
+		void setBufferSize(unsigned int size);
+
+		/**
+		* Sets the emission rate.
+		* @param rate The amount of particles per second.
+		**/
+		void setEmissionRate(int rate);
+
+		/**
+		* Sets the lifetime of the particle emitter (-1 means eternal)
+		* @param life The lifetime (in seconds).
+		**/
+		void setLifetime(float life);
+
+		/**
+		* Sets the life range of the particles.
+		* @param lifeMin The minimum life.
+		* @param lifeMax The maximum life (if 0, then becomes the same as minimum life).
+		**/
+		void setParticleLife(float min, float max = 0);
+
+		/**
+		* Sets the position of the center of the emitter and the direction (if set to relative).
+		* Used to move the emitter without changing the position of already existing particles.
+		* @param x The x-coordinate.
+		* @param y The y-coordinate.
+		**/
+		void setPosition(float x, float y);
+
+		/**
+		* Sets the direction and the spread of the particle emitter.
+		* @param direction The direction (in degrees).
+		**/
+		void setDirection(float direction);
+
+		/**
+		* Sets the spread of the particle emitter.
+		* @param spread The spread (in degrees).
+		**/
+		void setSpread(float spread);
+
+		/**
+		* Sets whether the direction should be relative to the particle emitters movement. Used in conjunction with setPosition.
+		* @param relative Whether to have relative direction.
+		**/
+		void setRelativeDirection(bool relative);
+
+		/**
+		* Sets the speed of the particles.
+		* @param speed The speed.
+		**/
+		void setSpeed(float speed);
+
+		/**
+		* Sets the speed of the particles.
+		* @param min The minimum speed.
+		* @param max The maximum speed.
+		**/
+		void setSpeed(float min, float max);
+
+		/**
+		* Sets the gravity of the particles (the acceleration along the y-axis).
+		* @param gravity The amount of gravity.
+		**/
+		void setGravity(float gravity);
+
+		/**
+		* Sets the gravity of the particles (the acceleration along the y-axis).
+		* @param min The minimum gravity.
+		* @param max The maximum gravity.
+		**/
+		void setGravity(float min, float max);
+
+		/**
+		* Sets the radial acceleration (the acceleration towards the particle emitter).
+		* @param acceleration The amount of acceleration.
+		**/
+		void setRadialAcceleration(float acceleration);
+
+		/**
+		* Sets the radial acceleration (the acceleration towards the particle emitter).
+		* @param min The minimum acceleration.
+		* @param max The maximum acceleration.
+		**/
+		void setRadialAcceleration(float min, float max);
+
+		/**
+		* Sets the tangential acceleration (the acceleration perpendicular to the particle's direction).
+		* @param acceleration The amount of acceleration.
+		**/
+		void setTangentialAcceleration(float acceleration);
+
+		/**
+		* Sets the tangential acceleration (the acceleration perpendicular to the particle's direction).
+		* @param min The minimum acceleration.
+		* @param max The maximum acceleration.
+		**/
+		void setTangentialAcceleration(float min, float max);
+
+		/**
+		* Sets the size of the sprite (1.0 being the default size).
+		* @param size The size of the sprite.
+		**/
+		void setSize(float size);
+
+		/**
+		* Sets the size of the sprite upon creation and upon death (1.0 being the default size).
+		* @param start The size of the sprite upon creation
+		* @param end The size of the sprite upon death.
+		**/
+		void setSize(float start, float end);
+
+		/**
+		* Sets the size of the sprite upon creation and upon death (1.0 being the default size) and any variation.
+		* @param start The size of the sprite upon creation
+		* @param end The size of the sprite upon death.
+		* @param variation The amount of variation on the starting size (0 being no variation and 1.0 a random size between start and end).
+		**/
+		void setSize(float start, float end, float variation);
+
+		/**
+		* Sets the amount of variation to the sprite's beginning size (0 being no variation and 1.0 a random size between start and end).
+		* @param variation The amount of variation.
+		**/
+		void setSizeVariation(float variation);
+
+		/**
+		* Sets the amount of rotation a sprite starts out with.
+		* @param rotation The amount of rotation.
+		**/
+		void setRotation(float rotation);
+
+		/**
+		* Sets the amount of rotation a sprite starts out with (a random value between min and max).
+		* @param min The minimum amount of rotation.
+		* @param max The maximum amount of rotation.
+		**/
+		void setRotation(float min, float max);
+
+		/**
+		* Sets the spin of the sprite.
+		* @param spin The spin of the sprite (in degrees).
+		**/
+		void setSpin(float spin);
+
+		/**
+		* Sets the spin of the sprite upon particle creation and death.
+		* @param start The spin of the sprite upon creation (in degrees).
+		* @param end The spin of the sprite upon death (in degrees).
+		**/
+		void setSpin(float start, float end);
+
+		/**
+		* Sets the spin of the sprite upon particle creation and death and the variation.
+		* @param start The spin of the sprite upon creation (in degrees).
+		* @param end The spin of the sprite upon death (in degrees).
+		* @param variation The variation of the start spin (0 being no variation and 1 beign a random spin between start and end).
+		**/
+		void setSpin(float start, float end, float variation);
+
+		/**
+		* Sets the variation of the start spin (0 being no variation and 1 beign a random spin between start and end).
+		* @param variation The variation in degrees.
+		**/
+		void setSpinVariation(float variation);
+
+		/**
+		* Sets the color of the particles.
+		* @param color The color.
+		**/
+		void setColor(unsigned char * color);
+
+		/**
+		* Sets the color of the particles.
+		* @param start The color of the particle when created.
+		* @param end The color of the particle upon death.
+		**/
+		void setColor(unsigned char * start, unsigned char * end);
+
+		/**
+		* Returns the x-coordinate of the emitter's position.
+		**/
+		float getX() const;
+
+		/**
+		* Returns the y-coordinate of the emitter's position.
+		**/
+		float getY() const;
+
+		/**
+		* Returns the direction of the emitter (in degrees).
+		**/
+		float getDirection() const;
+
+		/**
+		* Returns the directional spread of the emitter (in degrees).
+		**/
+		float getSpread() const;
+
+		/**
+		* Returns the amount of particles that are currently active in the system.
+		**/
+		int count() const;
+
+		/**
+		* Starts/resumes the particle emitter.
+		**/
+		void start();
+
+		/**
+		* Stops the particle emitter and resets.
+		**/
+		void stop();
+
+		/**
+		* Pauses the particle emitter.
+		**/
+		void pause();
+
+		/**
+		* Resets the particle emitter.
+		**/
+		void reset();
+
+		/**
+		* Returns whether the particle emitter is active.
+		**/
+		bool isActive() const;
+
+		/**
+		* Returns whether the particle system is empty of particles or not.
+		**/
+		bool isEmpty() const;
+
+		/**
+		* Returns whether the amount of particles has reached the buffer limit or not.
+		**/
+		bool isFull() const;
+
+		/**
+		* Draws the particle emitter at the specified position.
+		* @param x The x-coordinate.
+		* @param y The y-coordinate.
+		**/
+		virtual void draw(float x, float y, float angle, float sx, float sy, float ox, float oy) const;
+
+		/**
+		* Updates the particle system.
+		* @param dt Time since last update.
+		**/
+		void update(float dt);
+	};
+
+} // opengl
+} // graphics
+} // love
+
+#endif // LOVE_GRAPHICS_OPENGL_PARTICLE_SYSTEM_H

+ 2 - 1
src/modules/graphics/opengl/wrap_Graphics.cpp

@@ -758,7 +758,8 @@ namespace opengl
 		luaopen_image, 
 		luaopen_image, 
 		luaopen_glyph,
 		luaopen_glyph,
 		luaopen_frame, 
 		luaopen_frame, 
-		luaopen_spritebatch, 
+		luaopen_spritebatch,
+		luaopen_particlesystem,
 		0		
 		0		
 	};
 	};
 
 

+ 1 - 0
src/modules/graphics/opengl/wrap_Graphics.h

@@ -27,6 +27,7 @@
 #include "wrap_Glyph.h"
 #include "wrap_Glyph.h"
 #include "wrap_Quad.h"
 #include "wrap_Quad.h"
 #include "wrap_SpriteBatch.h"
 #include "wrap_SpriteBatch.h"
+#include "wrap_ParticleSystem.h"
 #include "Graphics.h"
 #include "Graphics.h"
 
 
 namespace love
 namespace love

+ 352 - 0
src/modules/graphics/opengl/wrap_ParticleSystem.cpp

@@ -0,0 +1,352 @@
+/**
+* Copyright (c) 2006-2009 LOVE Development Team
+* 
+* This software is provided 'as-is', without any express or implied
+* warranty.  In no event will the authors be held liable for any damages
+* arising from the use of this software.
+* 
+* Permission is granted to anyone to use this software for any purpose,
+* including commercial applications, and to alter it and redistribute it
+* freely, subject to the following restrictions:
+* 
+* 1. The origin of this software must not be misrepresented; you must not
+*    claim that you wrote the original software. If you use this software
+*    in a product, an acknowledgment in the product documentation would be
+*    appreciated but is not required.
+* 2. Altered source versions must be plainly marked as such, and must not be
+*    misrepresented as being the original software.
+* 3. This notice may not be removed or altered from any source distribution.
+**/
+
+#include "wrap_ParticleSystem.h"
+
+#include <cstring>
+
+namespace love
+{
+namespace graphics
+{
+namespace opengl
+{
+	ParticleSystem * luax_checkparticlesystem(lua_State * L, int idx)
+	{
+		return luax_checktype<ParticleSystem>(L, idx, "ParticleSystem", GRAPHICS_PARTICLE_SYSTEM_T);
+	}
+
+	int w_ParticleSystem_setSprite(lua_State * L)
+	{
+		ParticleSystem * t = luax_checkparticlesystem(L, 1);
+		Image * i = luax_checkimage(L, 2);
+		t->setSprite(i);
+		return 0;
+	}
+
+	int w_ParticleSystem_setBufferSize(lua_State * L)
+	{
+		ParticleSystem * t = luax_checkparticlesystem(L, 1);
+		int arg1 = luaL_checkint(L, 2);
+		t->setBufferSize((unsigned int)arg1);
+		return 0;
+	}
+
+	int w_ParticleSystem_setEmissionRate(lua_State * L)
+	{
+		ParticleSystem * t = luax_checkparticlesystem(L, 1);
+		int arg1 = luaL_checkint(L, 2);
+		t->setEmissionRate((unsigned int)arg1);
+		return 0;
+	}
+
+	int w_ParticleSystem_setLifetime(lua_State * L)
+	{
+		ParticleSystem * t = luax_checkparticlesystem(L, 1);
+		float arg1 = (float)luaL_checknumber(L, 2);
+		t->setLifetime(arg1);
+		return 0;
+	}
+
+	int w_ParticleSystem_setParticleLife(lua_State * L)
+	{
+		ParticleSystem * t = luax_checkparticlesystem(L, 1);
+		float arg1 = (float)luaL_checknumber(L, 2);
+		float arg2 = (float)luaL_checknumber(L, 3);
+		t->setParticleLife(arg1, arg2);
+		return 0;
+	}
+
+	int w_ParticleSystem_setPosition(lua_State * L)
+	{
+		ParticleSystem * t = luax_checkparticlesystem(L, 1);
+		float arg1 = (float)luaL_checknumber(L, 2);
+		float arg2 = (float)luaL_checknumber(L, 3);
+		t->setPosition(arg1, arg2);
+		return 0;
+	}
+
+	int w_ParticleSystem_setDirection(lua_State * L)
+	{
+		ParticleSystem * t = luax_checkparticlesystem(L, 1);
+		float arg1 = (float)luaL_checknumber(L, 2);
+		t->setDirection(arg1);
+		return 0;
+	}
+
+	int w_ParticleSystem_setSpread(lua_State * L)
+	{
+		ParticleSystem * t = luax_checkparticlesystem(L, 1);
+		float arg1 = (float)luaL_checknumber(L, 2);
+		t->setSpread(arg1);
+		return 0;
+	}
+
+	int w_ParticleSystem_setRelativeDirection(lua_State * L)
+	{
+		ParticleSystem * t = luax_checkparticlesystem(L, 1);
+		bool arg1 = (bool)luax_toboolean(L, 2);
+		t->setRelativeDirection(arg1);
+		return 0;
+	}
+
+	int w_ParticleSystem_setSpeed(lua_State * L)
+	{
+		ParticleSystem * t = luax_checkparticlesystem(L, 1);
+		float arg1 = (float)luaL_checknumber(L, 2);
+		float arg2 = (float)luaL_optnumber(L, 3, arg1);
+		t->setSpeed(arg1, arg2);
+		return 0;
+	}
+
+	int w_ParticleSystem_setGravity(lua_State * L)
+	{
+		ParticleSystem * t = luax_checkparticlesystem(L, 1);
+		float arg1 = (float)luaL_checknumber(L, 2);
+		float arg2 = (float)luaL_optnumber(L, 3, arg1);
+		t->setGravity(arg1, arg2);
+		return 0;
+	}
+
+	int w_ParticleSystem_setRadialAcceleration(lua_State * L)
+	{
+		ParticleSystem * t = luax_checkparticlesystem(L, 1);
+		float arg1 = (float)luaL_checknumber(L, 2);
+		float arg2 = (float)luaL_optnumber(L, 3, arg1);
+		t->setRadialAcceleration(arg1, arg2);
+		return 0;
+	}
+
+	int w_ParticleSystem_setTangentialAcceleration(lua_State * L)
+	{
+		ParticleSystem * t = luax_checkparticlesystem(L, 1);
+		float arg1 = (float)luaL_checknumber(L, 2);
+		float arg2 = (float)luaL_optnumber(L, 3, arg1);
+		t->setTangentialAcceleration(arg1, arg2);
+		return 0;
+	}
+
+	int w_ParticleSystem_setSize(lua_State * L)
+	{
+		ParticleSystem * t = luax_checkparticlesystem(L, 1);
+		float arg1 = (float)luaL_checknumber(L, 2);
+		float arg2 = (float)luaL_optnumber(L, 3, arg1);
+		float arg3 = (float)luaL_optnumber(L, 3, 0);
+		t->setSize(arg1, arg2, arg3);
+		return 0;
+	}
+
+	int w_ParticleSystem_setSizeVariation(lua_State * L)
+	{
+		ParticleSystem * t = luax_checkparticlesystem(L, 1);
+		float arg1 = (float)luaL_checknumber(L, 2);
+		t->setSizeVariation(arg1);
+		return 0;
+	}
+
+	int w_ParticleSystem_setRotation(lua_State * L)
+	{
+		ParticleSystem * t = luax_checkparticlesystem(L, 1);
+		float arg1 = (float)luaL_checknumber(L, 2);
+		float arg2 = (float)luaL_optnumber(L, 3, arg1);
+		t->setRotation(arg1, arg2);
+		return 0;
+	}
+
+	int w_ParticleSystem_setSpin(lua_State * L)
+	{
+		ParticleSystem * t = luax_checkparticlesystem(L, 1);
+		float arg1 = (float)luaL_checknumber(L, 2);
+		float arg2 = (float)luaL_optnumber(L, 3, arg1);
+		float arg3 = (float)luaL_optnumber(L, 3, 0);
+		t->setSpin(arg1, arg2, arg3);
+		return 0;
+	}
+
+	int w_ParticleSystem_setSpinVariation(lua_State * L)
+	{
+		ParticleSystem * t = luax_checkparticlesystem(L, 1);
+		float arg1 = (float)luaL_checknumber(L, 2);
+		t->setSpinVariation(arg1);
+		return 0;
+	}
+
+	int w_ParticleSystem_setColor(lua_State * L)
+	{
+		ParticleSystem * t = luax_checkparticlesystem(L, 1);
+		
+		unsigned char start[4];
+
+		start[0] = (unsigned char)luaL_checkint(L, 2);
+		start[1] = (unsigned char)luaL_checkint(L, 3);
+		start[2] = (unsigned char)luaL_checkint(L, 4);
+		start[3] = (unsigned char)luaL_checkint(L, 5);
+
+		if(lua_gettop(L) > 5)
+		{
+			unsigned char end[4];
+			end[0] = (unsigned char)luaL_checkint(L, 6);
+			end[1] = (unsigned char)luaL_checkint(L, 7);
+			end[2] = (unsigned char)luaL_checkint(L, 8);
+			end[3] = (unsigned char)luaL_checkint(L, 9);
+			t->setColor(start, end);
+		}
+		else
+			t->setColor(start);
+
+		return 0;
+	}
+
+	int w_ParticleSystem_getX(lua_State * L)
+	{
+		ParticleSystem * t = luax_checkparticlesystem(L, 1);
+		lua_pushnumber(L, t->getX());
+		return 1;
+	}
+
+	int w_ParticleSystem_getY(lua_State * L)
+	{
+		ParticleSystem * t = luax_checkparticlesystem(L, 1);
+		lua_pushnumber(L, t->getY());
+		return 1;
+	}
+
+	int w_ParticleSystem_getDirection(lua_State * L)
+	{
+		ParticleSystem * t = luax_checkparticlesystem(L, 1);
+		lua_pushnumber(L, t->getDirection());
+		return 1;
+	}
+
+	int w_ParticleSystem_getSpread(lua_State * L)
+	{
+		ParticleSystem * t = luax_checkparticlesystem(L, 1);
+		lua_pushnumber(L, t->getSpread());
+		return 1;
+	}
+
+	int w_ParticleSystem_count(lua_State * L)
+	{
+		ParticleSystem * t = luax_checkparticlesystem(L, 1);
+		lua_pushnumber(L, t->count());
+		return 1;
+	}
+
+	int w_ParticleSystem_start(lua_State * L)
+	{
+		ParticleSystem * t = luax_checkparticlesystem(L, 1);
+		t->start();
+		return 0;
+	}
+
+	int w_ParticleSystem_stop(lua_State * L)
+	{
+		ParticleSystem * t = luax_checkparticlesystem(L, 1);
+		t->stop();
+		return 0;
+	}
+
+	int w_ParticleSystem_pause(lua_State * L)
+	{
+		ParticleSystem * t = luax_checkparticlesystem(L, 1);
+		t->pause();
+		return 0;
+	}
+
+	int w_ParticleSystem_reset(lua_State * L)
+	{
+		ParticleSystem * t = luax_checkparticlesystem(L, 1);
+		t->reset();
+		return 0;
+	}
+
+	int w_ParticleSystem_isActive(lua_State * L)
+	{
+		ParticleSystem * t = luax_checkparticlesystem(L, 1);
+		luax_pushboolean(L, t->isActive());
+		return 1;
+	}
+
+	int w_ParticleSystem_isEmpty(lua_State * L)
+	{
+		ParticleSystem * t = luax_checkparticlesystem(L, 1);
+		luax_pushboolean(L, t->isEmpty());
+		return 1;
+	}
+
+	int w_ParticleSystem_isFull(lua_State * L)
+	{
+		ParticleSystem * t = luax_checkparticlesystem(L, 1);
+		luax_pushboolean(L, t->isFull());
+		return 1;
+	}
+
+	int w_ParticleSystem_update(lua_State * L)
+	{
+		ParticleSystem * t = luax_checkparticlesystem(L, 1);
+		float dt = (float)luaL_checknumber(L, 2);
+		t->update(dt);
+		return 0;
+	}
+
+	static const luaL_Reg functions[] = {
+		{ "setSprite", w_ParticleSystem_setSprite },
+		{ "setBufferSize", w_ParticleSystem_setBufferSize },
+		{ "setEmissionRate", w_ParticleSystem_setEmissionRate },
+		{ "setLifeTime", w_ParticleSystem_setLifetime },
+		{ "setParticleLife", w_ParticleSystem_setParticleLife },
+		{ "setPosition", w_ParticleSystem_setPosition },
+		{ "setDirection", w_ParticleSystem_setDirection },
+		{ "setSpread", w_ParticleSystem_setSpread },
+		{ "setRelativeDirection", w_ParticleSystem_setRelativeDirection },
+		{ "setSpeed", w_ParticleSystem_setSpeed },
+		{ "setGravity", w_ParticleSystem_setGravity },
+		{ "setRadialAcceleration", w_ParticleSystem_setRadialAcceleration },
+		{ "setTangentialAcceleration", w_ParticleSystem_setTangentialAcceleration },
+		{ "setSize", w_ParticleSystem_setSize },
+		{ "setSizeVariation", w_ParticleSystem_setSizeVariation },
+		{ "setRotation", w_ParticleSystem_setRotation },
+		{ "setSpin", w_ParticleSystem_setSpin },
+		{ "setSpinVariation", w_ParticleSystem_setSpinVariation },
+		{ "setColor", w_ParticleSystem_setColor },
+		{ "getX", w_ParticleSystem_getX },
+		{ "getY", w_ParticleSystem_getY },
+		{ "getDirection", w_ParticleSystem_getDirection },
+		{ "getSpread", w_ParticleSystem_getSpread },
+		{ "count", w_ParticleSystem_count },
+		{ "start", w_ParticleSystem_start },
+		{ "stop", w_ParticleSystem_stop },
+		{ "pause", w_ParticleSystem_pause },
+		{ "reset", w_ParticleSystem_reset },
+		{ "isActive", w_ParticleSystem_isActive },
+		{ "isEmpty", w_ParticleSystem_isEmpty },
+		{ "isFull", w_ParticleSystem_isFull },
+		{ "update", w_ParticleSystem_update },
+		{ 0, 0 }
+	};
+
+	int luaopen_particlesystem(lua_State * L)
+	{
+		return luax_register_type(L, "ParticleSystem", functions);
+	}
+
+} // opengl
+} // graphics
+} // love

+ 74 - 0
src/modules/graphics/opengl/wrap_ParticleSystem.h

@@ -0,0 +1,74 @@
+/**
+* Copyright (c) 2006-2009 LOVE Development Team
+* 
+* This software is provided 'as-is', without any express or implied
+* warranty.  In no event will the authors be held liable for any damages
+* arising from the use of this software.
+* 
+* Permission is granted to anyone to use this software for any purpose,
+* including commercial applications, and to alter it and redistribute it
+* freely, subject to the following restrictions:
+* 
+* 1. The origin of this software must not be misrepresented; you must not
+*    claim that you wrote the original software. If you use this software
+*    in a product, an acknowledgment in the product documentation would be
+*    appreciated but is not required.
+* 2. Altered source versions must be plainly marked as such, and must not be
+*    misrepresented as being the original software.
+* 3. This notice may not be removed or altered from any source distribution.
+**/
+
+#ifndef LOVE_GRAPHICS_OPENGL_WRAP_PARTICLE_SYSTEM_H
+#define LOVE_GRAPHICS_OPENGL_WRAP_PARTICLE_SYSTEM_H
+
+// LOVE
+#include <common/runtime.h>
+#include "wrap_Image.h"
+#include "ParticleSystem.h"
+
+namespace love
+{
+namespace graphics
+{
+namespace opengl
+{
+	ParticleSystem * luax_checkparticlesystem(lua_State * L, int idx);
+	int w_ParticleSystem_setSprite(lua_State * L);
+	int w_ParticleSystem_setBufferSize(lua_State * L);
+	int w_ParticleSystem_setEmissionRate(lua_State * L);
+	int w_ParticleSystem_setLifetime(lua_State * L);
+	int w_ParticleSystem_setParticleLife(lua_State * L);
+	int w_ParticleSystem_setPosition(lua_State * L);
+	int w_ParticleSystem_setDirection(lua_State * L);
+	int w_ParticleSystem_setSpread(lua_State * L);
+	int w_ParticleSystem_setRelativeDirection(lua_State * L);
+	int w_ParticleSystem_setSpeed(lua_State * L);
+	int w_ParticleSystem_setGravity(lua_State * L);
+	int w_ParticleSystem_setRadialAcceleration(lua_State * L);
+	int w_ParticleSystem_setTangentialAcceleration(lua_State * L);
+	int w_ParticleSystem_setSize(lua_State * L);
+	int w_ParticleSystem_setSizeVariation(lua_State * L);
+	int w_ParticleSystem_setRotation(lua_State * L);
+	int w_ParticleSystem_setSpin(lua_State * L);
+	int w_ParticleSystem_setSpinVariation(lua_State * L);
+	int w_ParticleSystem_setColor(lua_State * L);
+	int w_ParticleSystem_getX(lua_State * L);
+	int w_ParticleSystem_getY(lua_State * L);
+	int w_ParticleSystem_getDirection(lua_State * L);
+	int w_ParticleSystem_getSpread(lua_State * L);
+	int w_ParticleSystem_count(lua_State * L);
+	int w_ParticleSystem_start(lua_State * L);
+	int w_ParticleSystem_stop(lua_State * L);
+	int w_ParticleSystem_pause(lua_State * L);
+	int w_ParticleSystem_reset(lua_State * L);
+	int w_ParticleSystem_isActive(lua_State * L);
+	int w_ParticleSystem_isEmpty(lua_State * L);
+	int w_ParticleSystem_isFull(lua_State * L);
+	int w_ParticleSystem_update(lua_State * L);
+	int luaopen_particlesystem(lua_State * L);
+
+} // opengl
+} // graphics
+} // love
+
+#endif // LOVE_GRAPHICS_OPENGL_WRAP_PARTICLE_SYSTEM_H