Rename ParticleSystem:setAreaSpread to setEmissionArea, and move the functionality from setAreaSpreadAngle/setAreSpreadIsRelativeDirection into setEmissionArea. Resolves issue #1311.

This commit is contained in:
Alex Szpakowski
2018-01-13 21:11:07 -04:00
parent 2459752c06
commit ac52666c6f
3 changed files with 134 additions and 148 deletions
+55 -69
View File
@@ -65,9 +65,9 @@ ParticleSystem::ParticleSystem(Texture *texture, uint32 size)
, activeParticles(0)
, emissionRate(0)
, emitCounter(0)
, areaSpreadDistribution(DISTRIBUTION_NONE)
, areaSpreadAngle(0)
, areaSpreadIsRelativeDirection(false)
, emissionAreaDistribution(DISTRIBUTION_NONE)
, emissionAreaAngle(0)
, directionRelativeToEmissionCenter(false)
, lifetime(-1)
, life(0)
, particleLifeMin(0)
@@ -122,10 +122,10 @@ ParticleSystem::ParticleSystem(const ParticleSystem &p)
, emitCounter(0.0f)
, position(p.position)
, prevPosition(p.prevPosition)
, areaSpreadDistribution(p.areaSpreadDistribution)
, areaSpread(p.areaSpread)
, areaSpreadAngle(p.areaSpreadAngle)
, areaSpreadIsRelativeDirection(p.areaSpreadIsRelativeDirection)
, emissionAreaDistribution(p.emissionAreaDistribution)
, emissionArea(p.emissionArea)
, emissionAreaAngle(p.emissionAreaAngle)
, directionRelativeToEmissionCenter(p.directionRelativeToEmissionCenter)
, lifetime(p.lifetime)
, life(p.lifetime) // Initialize with the maximum life time.
, particleLifeMin(p.particleLifeMin)
@@ -275,61 +275,67 @@ void ParticleSystem::initParticle(Particle *p, float t)
// In this switch statement, variables 'rand_y', 'min', and 'max'
// are sometimes reused as data stores for performance reasons
float rand_x, rand_y;
switch (areaSpreadDistribution)
float c, s;
switch (emissionAreaDistribution)
{
case DISTRIBUTION_UNIFORM:
rand_x = (float) rng.random(-areaSpread.x, areaSpread.x);
rand_y = (float) rng.random(-areaSpread.y, areaSpread.y);
p->position.x += cosf(areaSpreadAngle) * rand_x - sinf(areaSpreadAngle) * rand_y;
p->position.y += sinf(areaSpreadAngle) * rand_x + cosf(areaSpreadAngle) * rand_y;
c = cosf(emissionAreaAngle); s = sinf(emissionAreaAngle);
rand_x = (float) rng.random(-emissionArea.x, emissionArea.x);
rand_y = (float) rng.random(-emissionArea.y, emissionArea.y);
p->position.x += c * rand_x - s * rand_y;
p->position.y += s * rand_x + c * rand_y;
break;
case DISTRIBUTION_NORMAL:
rand_x = (float) rng.randomNormal(areaSpread.x);
rand_y = (float) rng.randomNormal(areaSpread.y);
p->position.x += cosf(areaSpreadAngle) * rand_x - sinf(areaSpreadAngle) * rand_y;
p->position.y += sinf(areaSpreadAngle) * rand_x + cosf(areaSpreadAngle) * rand_y;
c = cosf(emissionAreaAngle); s = sinf(emissionAreaAngle);
rand_x = (float) rng.randomNormal(emissionArea.x);
rand_y = (float) rng.randomNormal(emissionArea.y);
p->position.x += c * rand_x - s * rand_y;
p->position.y += s * rand_x + c * rand_y;
break;
case DISTRIBUTION_ELLIPSE:
c = cosf(emissionAreaAngle); s = sinf(emissionAreaAngle);
rand_x = (float) rng.random(-1, 1);
rand_y = (float) rng.random(-1, 1);
min = areaSpread.x * (rand_x * sqrt(1 - 0.5f*pow(rand_y, 2)));
max = areaSpread.y * (rand_y * sqrt(1 - 0.5f*pow(rand_x, 2)));
p->position.x += cosf(areaSpreadAngle) * min - sinf(areaSpreadAngle) * max;
p->position.y += sinf(areaSpreadAngle) * min + cosf(areaSpreadAngle) * max;
min = emissionArea.x * (rand_x * sqrt(1 - 0.5f*pow(rand_y, 2)));
max = emissionArea.y * (rand_y * sqrt(1 - 0.5f*pow(rand_x, 2)));
p->position.x += c * min - s * max;
p->position.y += s * min + c * max;
break;
case DISTRIBUTION_BORDER_ELLIPSE:
c = cosf(emissionAreaAngle); s = sinf(emissionAreaAngle);
rand_x = (float) rng.random(0, LOVE_M_PI * 2);
min = cosf(rand_x) * areaSpread.x;
max = sinf(rand_x) * areaSpread.y;
p->position.x += cosf(areaSpreadAngle) * min - sinf(areaSpreadAngle) * max;
p->position.y += sinf(areaSpreadAngle) * min + cosf(areaSpreadAngle) * max;
min = cosf(rand_x) * emissionArea.x;
max = sinf(rand_x) * emissionArea.y;
p->position.x += c * min - s * max;
p->position.y += s * min + c * max;
break;
case DISTRIBUTION_BORDER_RECTANGLE:
rand_x = (float) rng.random((areaSpread.x + areaSpread.y) * -2, (areaSpread.x + areaSpread.y) * 2);
rand_y = areaSpread.y * 2;
c = cosf(emissionAreaAngle); s = sinf(emissionAreaAngle);
rand_x = (float) rng.random((emissionArea.x + emissionArea.y) * -2, (emissionArea.x + emissionArea.y) * 2);
rand_y = emissionArea.y * 2;
if (rand_x < -rand_y)
{
min = rand_x + rand_y + areaSpread.x;
p->position.x += cosf(areaSpreadAngle) * min - sinf(areaSpreadAngle) * -areaSpread.y;
p->position.y += sinf(areaSpreadAngle) * min + cosf(areaSpreadAngle) * -areaSpread.y;
min = rand_x + rand_y + emissionArea.x;
p->position.x += c * min - s * -emissionArea.y;
p->position.y += s * min + c * -emissionArea.y;
}
else if (rand_x < 0)
{
max = rand_x + areaSpread.y;
p->position.x += cosf(areaSpreadAngle) * -areaSpread.x - sinf(areaSpreadAngle) * max;
p->position.y += sinf(areaSpreadAngle) * -areaSpread.x + cosf(areaSpreadAngle) * max;
max = rand_x + emissionArea.y;
p->position.x += c * -emissionArea.x - s * max;
p->position.y += s * -emissionArea.x + c * max;
}
else if (rand_x < rand_y)
{
max = rand_x - areaSpread.y;
p->position.x += cosf(areaSpreadAngle) * areaSpread.x - sinf(areaSpreadAngle) * max;
p->position.y += sinf(areaSpreadAngle) * areaSpread.x + cosf(areaSpreadAngle) * max;
max = rand_x - emissionArea.y;
p->position.x += c * emissionArea.x - s * max;
p->position.y += s * emissionArea.x + c * max;
}
else
{
min = rand_x - rand_y - areaSpread.x;
p->position.x += cosf(areaSpreadAngle) * min - sinf(areaSpreadAngle) * areaSpread.y;
p->position.y += sinf(areaSpreadAngle) * min + cosf(areaSpreadAngle) * areaSpread.y;
min = rand_x - rand_y - emissionArea.x;
p->position.x += c * min - s * emissionArea.y;
p->position.y += s * min + c * emissionArea.y;
}
break;
case DISTRIBUTION_NONE:
@@ -338,7 +344,7 @@ void ParticleSystem::initParticle(Particle *p, float t)
}
// Determine if the origin of each particle is the center of the area
if (areaSpreadIsRelativeDirection)
if (directionRelativeToEmissionCenter)
dir += atan2(p->position.y - pos.y, p->position.x - pos.x);
p->origin = pos;
@@ -571,40 +577,20 @@ void ParticleSystem::moveTo(float x, float y)
position = love::Vector2(x, y);
}
void ParticleSystem::setAreaSpread(AreaSpreadDistribution distribution, float x, float y)
void ParticleSystem::setEmissionArea(AreaSpreadDistribution distribution, float x, float y, float angle, bool directionRelativeToCenter)
{
areaSpread = love::Vector2(x, y);
areaSpreadDistribution = distribution;
emissionArea = love::Vector2(x, y);
emissionAreaDistribution = distribution;
emissionAreaAngle = angle;
directionRelativeToEmissionCenter = directionRelativeToCenter;
}
ParticleSystem::AreaSpreadDistribution ParticleSystem::getAreaSpreadDistribution() const
ParticleSystem::AreaSpreadDistribution ParticleSystem::getEmissionArea(love::Vector2 &params, float &angle, bool &directionRelativeToCenter) const
{
return areaSpreadDistribution;
}
const love::Vector2 &ParticleSystem::getAreaSpreadParameters() const
{
return areaSpread;
}
void ParticleSystem::setAreaSpreadAngle(float angle)
{
areaSpreadAngle = angle;
}
float ParticleSystem::getAreaSpreadAngle() const
{
return areaSpreadAngle;
}
void ParticleSystem::setAreaSpreadIsRelativeDirection(bool isRelativeDirection)
{
areaSpreadIsRelativeDirection = isRelativeDirection;
}
bool ParticleSystem::getAreaSpreadIsRelativeDirection() const
{
return areaSpreadIsRelativeDirection;
params = emissionArea;
angle = emissionAreaAngle;
directionRelativeToCenter = directionRelativeToEmissionCenter;
return emissionAreaDistribution;
}
void ParticleSystem::setDirection(float direction)
+10 -36
View File
@@ -202,45 +202,19 @@ public:
* * Normal: Parameters denote the standard deviation in x and y direction. x and y are assumed to be uncorrelated.
* * borderellipse: Parameter causes particle distribution around outside of ellipse
* * borderrectangle: Parameter causes particle distribution around outside of rectangle
* @param distribution Distribution type
* @param x First parameter. Interpretation depends on distribution type.
* @param y Second parameter. Interpretation depends on distribution type.
* @param distribution Distribution type
* @param angle The angle of the emission area (in radians).
* @param directionRelativeToCenter whether the initial direction of
* particles points away from the center of the emission area.
**/
void setAreaSpread(AreaSpreadDistribution distribution, float x, float y);
/**
* Returns area spread distribution type.
**/
AreaSpreadDistribution getAreaSpreadDistribution() const;
void setEmissionArea(AreaSpreadDistribution distribution, float x, float y, float angle, bool directionRelativeToCenter);
/**
* Returns area spread parameters.
**/
const love::Vector2 &getAreaSpreadParameters() const;
/**
* Returns the angle of the area distribution (in radians).
**/
float getAreaSpreadAngle() const;
/**
* Sets the angle of the area distribution
* @param angle The angle (in radians).
**/
void setAreaSpreadAngle(float angle);
/**
* Returns true if particles spawn relative to the center of the
* shape area or false if they will use the setDirection parameter
**/
bool getAreaSpreadIsRelativeDirection() const;
/**
* Sets if particles starting direction is away from the center of the
* area spread or the setDirection parameter
* @param isRelativeDirection boolean use relative direction from center
**/
void setAreaSpreadIsRelativeDirection(bool isRelativeDirection);
AreaSpreadDistribution getEmissionArea(love::Vector2 &params, float &angle, bool &directionRelativeToCenter) const;
/**
* Sets the direction of the particle emitter.
@@ -636,10 +610,10 @@ private:
love::Vector2 prevPosition;
// Emission area spread.
AreaSpreadDistribution areaSpreadDistribution;
love::Vector2 areaSpread;
float areaSpreadAngle;
bool areaSpreadIsRelativeDirection;
AreaSpreadDistribution emissionAreaDistribution;
love::Vector2 emissionArea;
float emissionAreaAngle;
bool directionRelativeToEmissionCenter;
// The lifetime of the particle emitter (-1 means infinite) and the life it has left.
float lifetime;
+69 -43
View File
@@ -196,14 +196,16 @@ int w_ParticleSystem_moveTo(lua_State *L)
return 0;
}
int w_ParticleSystem_setAreaSpread(lua_State *L)
int w_ParticleSystem_setEmissionArea(lua_State *L)
{
ParticleSystem *t = luax_checkparticlesystem(L, 1);
ParticleSystem::AreaSpreadDistribution distribution = ParticleSystem::DISTRIBUTION_NONE;
float x = 0.f, y = 0.f;
float angle = 0.0f;
bool directionRelativeToCenter = false;
const char *str = lua_isnoneornil(L, 2) ? 0 : luaL_checkstring(L, 2);
const char *str = lua_isnoneornil(L, 2) ? nullptr : luaL_checkstring(L, 2);
if (str && !ParticleSystem::getConstant(str, distribution))
return luax_enumerror(L, "particle distribution", ParticleSystem::getConstants(distribution), str);
@@ -213,55 +215,32 @@ int w_ParticleSystem_setAreaSpread(lua_State *L)
y = (float) luaL_checknumber(L, 4);
if (x < 0.0f || y < 0.0f)
return luaL_error(L, "Invalid area spread parameters (must be >= 0)");
angle = (float) luaL_optnumber(L, 5, 0.0f);
directionRelativeToCenter = luax_optboolean(L, 6, false);
}
t->setAreaSpread(distribution, x, y);
t->setEmissionArea(distribution, x, y, angle, directionRelativeToCenter);
return 0;
}
int w_ParticleSystem_getAreaSpread(lua_State *L)
int w_ParticleSystem_getEmissionArea(lua_State *L)
{
ParticleSystem *t = luax_checkparticlesystem(L, 1);
ParticleSystem::AreaSpreadDistribution distribution = t-> getAreaSpreadDistribution();
love::Vector2 p;
float angle;
bool directionRelativeToCenter;
ParticleSystem::AreaSpreadDistribution distribution = t->getEmissionArea(p, angle, directionRelativeToCenter);
const char *str;
ParticleSystem::getConstant(distribution, str);
const love::Vector2 &p = t->getAreaSpreadParameters();
lua_pushstring(L, str);
lua_pushnumber(L, p.x);
lua_pushnumber(L, p.y);
lua_pushnumber(L, angle);
luax_pushboolean(L, directionRelativeToCenter);
return 3;
}
int w_ParticleSystem_setAreaSpreadAngle(lua_State *L)
{
ParticleSystem *t = luax_checkparticlesystem(L, 1);
float arg1 = (float)luaL_checknumber(L, 2);
t->setAreaSpreadAngle(arg1);
return 0;
}
int w_ParticleSystem_getAreaSpreadAngle(lua_State *L)
{
ParticleSystem *t = luax_checkparticlesystem(L, 1);
lua_pushnumber(L, t->getAreaSpreadAngle());
return 1;
}
int w_ParticleSystem_setAreaSpreadIsRelativeDirection(lua_State *L)
{
ParticleSystem *t = luax_checkparticlesystem(L, 1);
bool arg1 = luax_checkboolean(L, 2);
t->setAreaSpreadIsRelativeDirection(arg1);
return 0;
}
int w_ParticleSystem_getAreaSpreadIsRelativeDirection(lua_State *L)
{
ParticleSystem *t = luax_checkparticlesystem(L, 1);
luax_pushboolean(L, t->getAreaSpreadIsRelativeDirection());
return 1;
return 5;
}
int w_ParticleSystem_setDirection(lua_State *L)
@@ -734,6 +713,52 @@ int w_ParticleSystem_update(lua_State *L)
return 0;
}
// Deprecated functions.
int w_ParticleSystem_setAreaSpread(lua_State *L)
{
luax_markdeprecated(L, "ParticleSystem:setAreaSpread", API_METHOD, DEPRECATED_REPLACED, "ParticleSystem:setEmissionArea");
ParticleSystem *t = luax_checkparticlesystem(L, 1);
ParticleSystem::AreaSpreadDistribution distribution = ParticleSystem::DISTRIBUTION_NONE;
float x = 0.f, y = 0.f;
const char *str = lua_isnoneornil(L, 2) ? 0 : luaL_checkstring(L, 2);
if (str && !ParticleSystem::getConstant(str, distribution))
return luax_enumerror(L, "particle distribution", ParticleSystem::getConstants(distribution), str);
if (distribution != ParticleSystem::DISTRIBUTION_NONE)
{
x = (float) luaL_checknumber(L, 3);
y = (float) luaL_checknumber(L, 4);
if (x < 0.0f || y < 0.0f)
return luaL_error(L, "Invalid area spread parameters (must be >= 0)");
}
t->setEmissionArea(distribution, x, y, 0.0f, false);
return 0;
}
int w_ParticleSystem_getAreaSpread(lua_State *L)
{
luax_markdeprecated(L, "ParticleSystem:getAreaSpread", API_METHOD, DEPRECATED_REPLACED, "ParticleSystem:getEmissionArea");
ParticleSystem *t = luax_checkparticlesystem(L, 1);
love::Vector2 p;
float angle;
bool unused;
ParticleSystem::AreaSpreadDistribution distribution = t->getEmissionArea(p, angle, unused);
const char *str;
ParticleSystem::getConstant(distribution, str);
lua_pushstring(L, str);
lua_pushnumber(L, p.x);
lua_pushnumber(L, p.y);
return 3;
}
static const luaL_Reg w_ParticleSystem_functions[] =
{
{ "clone", w_ParticleSystem_clone },
@@ -752,12 +777,8 @@ static const luaL_Reg w_ParticleSystem_functions[] =
{ "setPosition", w_ParticleSystem_setPosition },
{ "getPosition", w_ParticleSystem_getPosition },
{ "moveTo", w_ParticleSystem_moveTo },
{ "setAreaSpread", w_ParticleSystem_setAreaSpread },
{ "getAreaSpread", w_ParticleSystem_getAreaSpread },
{ "setAreaSpreadAngle", w_ParticleSystem_setAreaSpreadAngle },
{ "getAreaSpreadAngle", w_ParticleSystem_getAreaSpreadAngle },
{ "setAreaSpreadIsRelativeDirection", w_ParticleSystem_setAreaSpreadIsRelativeDirection },
{ "getAreaSpreadIsRelativeDirection", w_ParticleSystem_getAreaSpreadIsRelativeDirection },
{ "setEmissionArea", w_ParticleSystem_setEmissionArea },
{ "getEmissionArea", w_ParticleSystem_getEmissionArea },
{ "setDirection", w_ParticleSystem_setDirection },
{ "getDirection", w_ParticleSystem_getDirection },
{ "setSpread", w_ParticleSystem_setSpread },
@@ -800,6 +821,11 @@ static const luaL_Reg w_ParticleSystem_functions[] =
{ "isPaused", w_ParticleSystem_isPaused },
{ "isStopped", w_ParticleSystem_isStopped },
{ "update", w_ParticleSystem_update },
// Deprecated.
{ "setAreaSpread", w_ParticleSystem_setAreaSpread },
{ "getAreaSpread", w_ParticleSystem_getAreaSpread },
{ 0, 0 }
};