diff --git a/platform/msvc2008/graphics/graphics.vcproj b/platform/msvc2008/graphics/graphics.vcproj
index f5edfdd0e..a2a5d9c73 100644
--- a/platform/msvc2008/graphics/graphics.vcproj
+++ b/platform/msvc2008/graphics/graphics.vcproj
@@ -172,6 +172,18 @@
+
+
+
+
+
@@ -269,6 +281,22 @@
RelativePath="..\..\..\src\modules\graphics\opengl\ImageFont.h"
>
+
+
+
+
+
+
+
@@ -373,6 +401,22 @@
RelativePath="..\..\..\src\modules\graphics\opengl\wrap_Image.h"
>
+
+
+
+
+
+
+
@@ -398,18 +442,6 @@
>
-
-
-
-
-
diff --git a/platform/msvc2008/love.vcproj b/platform/msvc2008/love.vcproj
index b406fa9e3..77b3c0991 100644
--- a/platform/msvc2008/love.vcproj
+++ b/platform/msvc2008/love.vcproj
@@ -925,6 +925,22 @@
RelativePath="..\..\src\modules\graphics\opengl\ImageFont.h"
>
+
+
+
+
+
+
+
@@ -1045,6 +1061,22 @@
RelativePath="..\..\src\modules\graphics\opengl\wrap_Image.h"
>
+
+
+
+
+
+
+
diff --git a/src/modules/graphics/opengl/ParticleSystem.cpp b/src/modules/graphics/opengl/ParticleSystem.cpp
new file mode 100644
index 000000000..fef667741
--- /dev/null
+++ b/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
+#include
+#include
+#include
+
+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
diff --git a/src/modules/graphics/opengl/ParticleSystem.h b/src/modules/graphics/opengl/ParticleSystem.h
new file mode 100644
index 000000000..936a38b1a
--- /dev/null
+++ b/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
+#include
+#include
+#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
diff --git a/src/modules/graphics/opengl/wrap_Graphics.cpp b/src/modules/graphics/opengl/wrap_Graphics.cpp
index 277587a10..c273e2578 100644
--- a/src/modules/graphics/opengl/wrap_Graphics.cpp
+++ b/src/modules/graphics/opengl/wrap_Graphics.cpp
@@ -758,7 +758,8 @@ namespace opengl
luaopen_image,
luaopen_glyph,
luaopen_frame,
- luaopen_spritebatch,
+ luaopen_spritebatch,
+ luaopen_particlesystem,
0
};
diff --git a/src/modules/graphics/opengl/wrap_Graphics.h b/src/modules/graphics/opengl/wrap_Graphics.h
index 9e668ba61..604ab6a20 100644
--- a/src/modules/graphics/opengl/wrap_Graphics.h
+++ b/src/modules/graphics/opengl/wrap_Graphics.h
@@ -27,6 +27,7 @@
#include "wrap_Glyph.h"
#include "wrap_Quad.h"
#include "wrap_SpriteBatch.h"
+#include "wrap_ParticleSystem.h"
#include "Graphics.h"
namespace love
diff --git a/src/modules/graphics/opengl/wrap_ParticleSystem.cpp b/src/modules/graphics/opengl/wrap_ParticleSystem.cpp
new file mode 100644
index 000000000..3193e92f8
--- /dev/null
+++ b/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
+
+namespace love
+{
+namespace graphics
+{
+namespace opengl
+{
+ ParticleSystem * luax_checkparticlesystem(lua_State * L, int idx)
+ {
+ return luax_checktype(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
diff --git a/src/modules/graphics/opengl/wrap_ParticleSystem.h b/src/modules/graphics/opengl/wrap_ParticleSystem.h
new file mode 100644
index 000000000..d42c020d3
--- /dev/null
+++ b/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
+#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