Mercurial > love-experiments
diff src/modules/graphics/opengl/ParticleSystem.cpp @ 1127:13e6ca38c28c
Fix issue #437: Area-based particle spawn.
New particles are spawned around the particle emitter position according to a
configurabe distribution.
New functionality:
particlesystem:setAreaSpread(distributon, x, y)
distribution, x, y = particlesystem:getAreaSpread()
Where `distribution' is one of "none", "uniform", "normal".
`x' and `y' take different meaning based on the distribution:
* none: no area spread - particles spawned at emitter position.
* uniform: particle spawned at px,py in the rectangle around emitter
position ex,ey, i.e.:
ex - x < px < ex + x, ey - y < py < ey + y,
* normal: particle position drawn from a normal/gaussian distribution
with mean ex,ey and standard deviation x,y, i.e.:
px \in N(ex, x²), py \in N(ey, y²).
| author | vrld <vrld@vrld.org> |
|---|---|
| date | Mon, 10 Sep 2012 19:58:44 +0200 |
| parents | 86a44f2bc38f |
| children | 7c7332becb70 77889bd62149 |
line wrap: on
line diff
--- a/src/modules/graphics/opengl/ParticleSystem.cpp Mon Sep 10 19:45:54 2012 +0200 +++ b/src/modules/graphics/opengl/ParticleSystem.cpp Mon Sep 10 19:58:44 2012 +0200 @@ -45,10 +45,18 @@ { float low = inner - (outer/2.0f)*var; float high = inner + (outer/2.0f)*var; - float r = (rand() / (float(RAND_MAX)+1)); + float r = random(); return low*(1-r)+high*r; } +StringMap<ParticleSystem::AreaSpreadDistribution, ParticleSystem::DISTRIBUTION_MAX_ENUM>::Entry ParticleSystem::distributionsEntries[] = { + { "none", ParticleSystem::DISTRIBUTION_NONE }, + { "uniform", ParticleSystem::DISTRIBUTION_UNIFORM }, + { "normal", ParticleSystem::DISTRIBUTION_NORMAL }, +}; + +StringMap<ParticleSystem::AreaSpreadDistribution, ParticleSystem::DISTRIBUTION_MAX_ENUM> ParticleSystem::distributions(ParticleSystem::distributionsEntries, sizeof(ParticleSystem::distributionsEntries)); + ParticleSystem::ParticleSystem(Image *sprite, unsigned int buffer) : pStart(0) @@ -57,6 +65,7 @@ , active(true) , emissionRate(0) , emitCounter(0) + , areaSpreadDistribution(DISTRIBUTION_NONE) , lifetime(-1) , life(0) , particleLifeMin(0) @@ -108,45 +117,60 @@ if (min == max) pLast->life = min; else - pLast->life = (rand() / (float(RAND_MAX)+1)) * (max - min) + min; + pLast->life = random(min, max); pLast->lifetime = pLast->life; pLast->position[0] = position.getX(); pLast->position[1] = position.getY(); + switch (areaSpreadDistribution) + { + case DISTRIBUTION_UNIFORM: + pLast->position[0] += random(-areaSpread.getX(), areaSpread.getX()); + pLast->position[1] += random(-areaSpread.getY(), areaSpread.getY()); + break; + case DISTRIBUTION_NORMAL: + pLast->position[0] += random_normal(areaSpread.getX()); + pLast->position[1] += random_normal(areaSpread.getY()); + break; + case DISTRIBUTION_NONE: + default: + break; + } + min = direction - spread/2.0f; max = direction + spread/2.0f; - pLast->direction = (rand() / (float(RAND_MAX)+1)) * (max - min) + min; + pLast->direction = random(min, max); pLast->origin = position; min = speedMin; max = speedMax; - float speed = (rand() / (float(RAND_MAX)+1)) * (max - min) + min; + float speed = random(min, max); 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; + pLast->gravity = random(min, max); min = radialAccelerationMin; max = radialAccelerationMax; - pLast->radialAcceleration = (rand() / (float(RAND_MAX)+1)) * (max - min) + min; + pLast->radialAcceleration = random(min, max); min = tangentialAccelerationMin; max = tangentialAccelerationMax; - pLast->tangentialAcceleration = (rand() / (float(RAND_MAX)+1)) * (max - min) + min; + pLast->tangentialAcceleration = random(min, max); - pLast->sizeOffset = (rand() / (float(RAND_MAX)+1)) * sizeVariation; // time offset for size change - pLast->sizeIntervalSize = (1.0f - (rand() / (float(RAND_MAX)+1)) * sizeVariation) - pLast->sizeOffset; + pLast->sizeOffset = random(sizeVariation); // time offset for size change + pLast->sizeIntervalSize = (1.0f - random(sizeVariation)) - pLast->sizeOffset; pLast->size = sizes[(size_t)(pLast->sizeOffset - .5f) * (sizes.size() - 1)]; 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->rotation = random(min, max); pLast->color = colors[0]; @@ -204,6 +228,13 @@ position = love::Vector(x, y); } + +void ParticleSystem::setAreaSpread(AreaSpreadDistribution distribution, float x, float y) +{ + areaSpread = love::Vector(x, y); + areaSpreadDistribution = distribution; +} + void ParticleSystem::setDirection(float direction) { this->direction = direction; @@ -349,6 +380,16 @@ return position; } +ParticleSystem::AreaSpreadDistribution ParticleSystem::getAreaSpreadDistribution() const +{ + return areaSpreadDistribution; +} + +const love::Vector &ParticleSystem::getAreaSpreadParameters() const +{ + return areaSpread; +} + float ParticleSystem::getDirection() const { return direction; @@ -543,6 +584,16 @@ } // while } +bool ParticleSystem::getConstant(const char *in, AreaSpreadDistribution &out) +{ + return distributions.find(in, out); +} + +bool ParticleSystem::getConstant(AreaSpreadDistribution in, const char *&out) +{ + return distributions.find(in, out); +} + } // opengl } // graphics } // love
