mirror of
https://github.com/love2d/love.git
synced 2026-08-13 17:10:54 +02:00
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²).
This commit is contained in:
@@ -45,10 +45,18 @@ 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));
|
||||
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 @@ ParticleSystem::ParticleSystem(Image *sprite, unsigned int buffer)
|
||||
, active(true)
|
||||
, emissionRate(0)
|
||||
, emitCounter(0)
|
||||
, areaSpreadDistribution(DISTRIBUTION_NONE)
|
||||
, lifetime(-1)
|
||||
, life(0)
|
||||
, particleLifeMin(0)
|
||||
@@ -108,45 +117,60 @@ void ParticleSystem::add()
|
||||
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 @@ void ParticleSystem::setPosition(float x, float y)
|
||||
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 @@ const love::Vector &ParticleSystem::getPosition() const
|
||||
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 @@ void ParticleSystem::update(float dt)
|
||||
} // 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
|
||||
|
||||
Reference in New Issue
Block a user