1
0
Fork 0
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:
fgenesis 2025-02-05 04:54:37 +01:00
parent 7b442174c8
commit 68c29a3fc9
3 changed files with 36 additions and 23 deletions

View file

@ -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();
}

View file

@ -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();

View file

@ -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