mirror of
https://github.com/AquariaOSE/Aquaria.git
synced 2025-04-07 23:27:12 +00:00
Improve particle spawning behavior; small cleanup
Apparently there was an interpolation scheme in place to spawn quickly-spawning (ie more than 1 per frame) particles along a line interpolated between the previous and current position, but the math was incorrect and it always ended up spawning all particles on the same spot.
This commit is contained in:
parent
7b442174c8
commit
68c29a3fc9
3 changed files with 36 additions and 23 deletions
|
@ -41,7 +41,6 @@ SpawnParticleData::SpawnParticleData()
|
|||
color = Vector(1,1,1);
|
||||
alpha = 1;
|
||||
randomSpawnRadius = 0;
|
||||
lastDTDifference = 0;
|
||||
|
||||
randomRotationRange = 0;
|
||||
number = 1;
|
||||
|
@ -52,7 +51,7 @@ SpawnParticleData::SpawnParticleData()
|
|||
randomVelocityMagnitude = 0;
|
||||
|
||||
copyParentRotation = 0;
|
||||
justOne = didOne = false;
|
||||
justOne = false;
|
||||
flipH = flipV = 0;
|
||||
spawnTimeOffset = 0;
|
||||
pauseLevel = 0;
|
||||
|
@ -80,7 +79,7 @@ void Emitter::destroy()
|
|||
|
||||
}
|
||||
|
||||
void Emitter::spawnParticle(float perc)
|
||||
Particle *Emitter::spawnParticle(const Vector& spawnpos)
|
||||
{
|
||||
Particle *p = particleManager->getFreeParticle(this);
|
||||
|
||||
|
@ -101,7 +100,7 @@ void Emitter::spawnParticle(float perc)
|
|||
|
||||
p->rot = data.rotation;
|
||||
|
||||
p->pos = lastSpawn + ((currentSpawn - lastSpawn) * perc);
|
||||
p->pos = spawnpos;
|
||||
|
||||
float finalRadius = data.randomSpawnRadius + rng.f01() * data.randomSpawnRadiusRange;
|
||||
|
||||
|
@ -135,6 +134,8 @@ void Emitter::spawnParticle(float perc)
|
|||
{
|
||||
p->rot.z = getAbsoluteRotation().z;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
float Emitter::randAngle()
|
||||
|
@ -162,27 +163,26 @@ void Emitter::onUpdate(float dt)
|
|||
data.spawnTimeOffset -= dt;
|
||||
if (data.spawnTimeOffset > 0)
|
||||
return;
|
||||
lastSpawn = getSpawnPosition();
|
||||
}
|
||||
|
||||
int spawnCount;
|
||||
int spawnCount = 0;
|
||||
float spawnPerc;
|
||||
if (data.justOne)
|
||||
{
|
||||
if (data.didOne)
|
||||
spawnCount = 0;
|
||||
else
|
||||
if (!didOne)
|
||||
spawnCount = data.justOne;
|
||||
spawnPerc = 1;
|
||||
data.didOne = 1;
|
||||
spawnPerc = 0; // Spawn all of them in the same spot
|
||||
didOne = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
float num = data.number.x * dt;
|
||||
num += data.lastDTDifference;
|
||||
num += lastDTDifference;
|
||||
spawnCount = int(num);
|
||||
data.lastDTDifference = num - float(spawnCount);
|
||||
lastDTDifference = num - float(spawnCount);
|
||||
if (spawnCount > 0)
|
||||
spawnPerc = 1.0f / float(spawnCount);
|
||||
spawnPerc = 1.0f / num;
|
||||
}
|
||||
|
||||
if (spawnCount > 0)
|
||||
|
@ -190,16 +190,23 @@ void Emitter::onUpdate(float dt)
|
|||
// Avoid calling this until we know we actually need it for
|
||||
// generating a particle (it has to apply the matrix chain,
|
||||
// which is slow).
|
||||
currentSpawn = getSpawnPosition();
|
||||
if (lastSpawn.isZero())
|
||||
lastSpawn = currentSpawn;
|
||||
const Vector currentSpawn = getSpawnPosition();
|
||||
|
||||
for (; spawnCount > 0; spawnCount--)
|
||||
// Given the last spawn position and the new spawn position, interpolate as many particles
|
||||
// along the line between both positions. Start at current and move back to prev.
|
||||
// For convenience, 0 is the current pos and 1 is the prev. pos.
|
||||
float percAccu = 0;
|
||||
for(int i = 0; i < spawnCount; ++i)
|
||||
{
|
||||
spawnParticle(spawnPerc);
|
||||
spawnParticle(lerp(currentSpawn, lastSpawn, percAccu));
|
||||
// This is unlikely to reach 1 perfectly, which is good since what is currently 1
|
||||
// was 0 in the previous iteration, and that is known to be hit perfectly.
|
||||
// This way we usually don't end up placing 2 particles in the same spot.
|
||||
percAccu += spawnPerc;
|
||||
}
|
||||
|
||||
lastSpawn = currentSpawn;
|
||||
|
||||
}
|
||||
|
||||
data.number.update(dt);
|
||||
|
@ -207,7 +214,8 @@ void Emitter::onUpdate(float dt)
|
|||
|
||||
void Emitter::start()
|
||||
{
|
||||
data.didOne = 0;
|
||||
didOne = false;
|
||||
lastDTDifference = 0;
|
||||
lastSpawn = getSpawnPosition();
|
||||
}
|
||||
|
||||
|
|
|
@ -44,7 +44,6 @@ struct SpawnParticleData
|
|||
float randomSpawnRadius;
|
||||
Vector randomSpawnMod;
|
||||
int randomSpawnRadiusRange;
|
||||
bool didOne;
|
||||
int justOne;
|
||||
|
||||
int copyParentRotation, copyParentFlip;
|
||||
|
@ -58,7 +57,6 @@ struct SpawnParticleData
|
|||
bool inheritColor;
|
||||
bool inheritAlpha;
|
||||
|
||||
float lastDTDifference;
|
||||
int influenced;
|
||||
std::string deathPrt;
|
||||
|
||||
|
@ -120,9 +118,11 @@ public:
|
|||
|
||||
bool hasRot; // FIXME: this should be removed eventually
|
||||
protected:
|
||||
Vector currentSpawn, lastSpawn;
|
||||
Vector lastSpawn;
|
||||
float lastDTDifference;
|
||||
bool didOne;
|
||||
void onRender(const RenderState& rs) const OVERRIDE;
|
||||
void spawnParticle(float perc=1);
|
||||
Particle *spawnParticle(const Vector& spawnpos);
|
||||
void onUpdate(float dt) OVERRIDE;
|
||||
float randAngle();
|
||||
|
||||
|
|
|
@ -526,6 +526,11 @@ public:
|
|||
|
||||
Vector getRotatedVector(const Vector &vec, float rot);
|
||||
|
||||
inline Vector lerp(const Vector &v1, const Vector &v2, float t)
|
||||
{
|
||||
return (v2-v1)*t+v1;
|
||||
}
|
||||
|
||||
Vector lerp(const Vector &v1, const Vector &v2, float dt, int lerpType);
|
||||
|
||||
#endif // BBGE_VECTOR_H
|
||||
|
|
Loading…
Add table
Reference in a new issue