Commits

Alex Szpakowski committed 12c2378

Changed particle spawning behaviour in ParticleSystems to spawn at an interpolated position between the location at the previous update and the current one. This results in much smoother behaviour when moving a ParticleSystem constantly via ParticleSystem:setPosition.
Also fixed particle spawning to better fill up the buffer.

Comments (0)

Files changed (2)

src/modules/graphics/opengl/ParticleSystem.cpp

 	, emissionRate(p.emissionRate)
 	, emitCounter(0.0f)
 	, position(p.position)
+	, prevPosition(p.prevPosition)
 	, areaSpreadDistribution(p.areaSpreadDistribution)
 	, areaSpread(p.areaSpread)
 	, lifetime(p.lifetime)
 	return maxParticles;
 }
 
-void ParticleSystem::addParticle()
+void ParticleSystem::addParticle(float t)
 {
 	if (isFull())
 		return;
 
 	// Gets a free particle and updates the allocation pointer.
 	particle *p = pFree++;
-	initParticle(p);
+	initParticle(p, t);
 
 	switch (insertMode)
 	{
 	activeParticles++;
 }
 
-void ParticleSystem::initParticle(particle *p)
+void ParticleSystem::initParticle(particle *p, float t)
 {
 	float min,max;
 
+	// Linearly interpolate between the previous and current emitter position.
+	love::Vector pos = prevPosition + (position - prevPosition) * t;
+
 	min = particleLifeMin;
 	max = particleLifeMax;
 	if (min == max)
 		p->life = (float) rng.random(min, max);
 	p->lifetime = p->life;
 
-	p->position[0] = position.getX();
-	p->position[1] = position.getY();
+	p->position[0] = pos.x;
+	p->position[1] = pos.y;
 
 	switch (areaSpreadDistribution)
 	{
 	max = direction + spread/2.0f;
 	p->direction = (float) rng.random(min, max);
 
-	p->origin = position;
+	p->origin = pos;
 
 	min = speedMin;
 	max = speedMax;
 	num = std::min(num, maxParticles - activeParticles);
 
 	while(num--)
-		addParticle();
+		addParticle(1.0f);
 }
 
 bool ParticleSystem::isActive() const
 	if (pMem == nullptr || dt == 0.0f)
 		return;
 
-	// Make some more particles.
-	if (active)
-	{
-		float rate = 1.0f / emissionRate; // the amount of time between each particle emit
-		emitCounter += dt;
-		while (emitCounter > rate)
-		{
-			addParticle();
-			emitCounter -= rate;
-		}
-		/*int particles = (int)(emissionRate * dt);
-		for (int i = 0; i != particles; i++)
-			add();*/
-
-		life -= dt;
-		if (lifetime != -1 && life < 0)
-			stop();
-	}
-
 	// Traverse all particles and update.
 	particle *p = pHead;
 
 			p = p->next;
 		}
 	}
+
+	// Make some more particles.
+	if (active)
+	{
+		float rate = 1.0f / emissionRate; // the amount of time between each particle emit
+		emitCounter += dt;
+		float total = emitCounter - rate;
+		while (emitCounter > rate)
+		{
+			addParticle(1.0f - (emitCounter - rate) / total);
+			emitCounter -= rate;
+		}
+		/*int particles = (int)(emissionRate * dt);
+		 for (int i = 0; i != particles; i++)
+		 add();*/
+
+		life -= dt;
+		if (lifetime != -1 && life < 0)
+			stop();
+	}
+
+	prevPosition = position;
 }
 
 bool ParticleSystem::getConstant(const char *in, AreaSpreadDistribution &out)

src/modules/graphics/opengl/ParticleSystem.h

 
 	// The relative position of the particle emitter.
 	love::Vector position;
+	love::Vector prevPosition;
 
 	// Emission area spread.
 	AreaSpreadDistribution areaSpreadDistribution;
 	void createBuffers(size_t size);
 	void deleteBuffers();
 
-	void addParticle();
+	void addParticle(float t);
 	particle *removeParticle(particle *p);
 
 	// Called by addParticle.
-	void initParticle(particle *p);
+	void initParticle(particle *p, float t);
 	void insertTop(particle *p);
 	void insertBottom(particle *p);
 	void insertRandom(particle *p);