Add New Particle System with event


#1

I am trying to add a new particle system every time a certain event occurs. I am initializing an ellipse moving upward with mousePressed and once it passes a certain threshold a particle system appears. However, I can only manage for this to happen once. When I launch a second ellipse and it passes that threshold, nothing happens. Any help would be appreciated!

Code: https://github.com/Nedelstein/edeln591_dtOF_2018/tree/master/w06_h01_fireworks

Thanks,
Noah


#2

hi there!

line 34 in ParticleSystem.cpp

for(int i; i<particles.size(); i ++){

just have to reinitialize i back to 0. That fixed it for me.


#3

Ah amazing thank you! It’s always those little things that get me.


#4

Hey Adam,

Another question if you don’t mind:

How do I get each particle system occurrence to fade over time? That is, once they’ve been triggered by the firework, how can I get them to slowly fade away? I’ve tried using alpha channels, but haven’t been successful.

Thanks,
Noah


#5

Hi Noah,
oh sure, yea, i suppose there would be different ways to do this depending on the effect you are trying to achieve, but i think what we want in this case is: after a set amount of time the entire Particle System slowly fades away and once it does it gets removed form the particleSystems vector.
The way I would do it is to give the Particle system a life span variable, decrement it in the ParticleSystem update(), and once it hits zero fade out the system. You are already fading individual particles, so I would create a fadeScale variable to scale all those alpha values, and the fadeScale is what gets decremented once the Particle System’s life span hits zero.
So, i guess something like this—
in ParticleSystem.hpp add:

float lifeSpan = 500;   // or however long you want it to live
float systemFade = 1.0;

then in ParticleSystem.cpp, at the end of the class update(), add:

lifeSpan--;

if (lifeSpan < 0) {
    systemFadeScale -= 0.3;
}

So we will only trigger the fading once lifeSpan hits zero.

Moving on to implementing the fading,
in Particle.hpp add:

float fadeScale;

in Particle.cpp, in the draw function where you are setting the color of circle, scale alpha by fadeScale, so the line will now be:

ofSetColor(ofRandom(100,255),ofRandom(100,255), ofRandom(100,255), fade * fadeScale);

Also, I am not sure if Enabling/Disabling Alpha Blending here is doing anything. Alpha Blending is on by default. but i dont know, maybe you have a specific reason for doing this.

Back in ParticleSystem.cpp, in the for-loop you are using to call update on your particles, add a line to access the particles fadeScale:

    for (int i = 0; i < particles.size(); i++){
		particles[i].fadeScale = systemFade;
        particles[i].update();
    }

Great, so this will fade out the entire system after a specific time, but we still have to remove it from the particleSystems vector. I can think of two ways to do this right off the bat and I am not sure which is technically better or more “right”. So I’ll do both and hopefully eventually someone who knows more than us can tell us the benefits of using one over the other in this situation.
One way is to use indices ( [ ] ). We just have to add an if() statement to check if the systemFade is less than 0, if it is then remove the system.

    for (int i =0; i<particleSystems.size(); i++) {
        particleSystems[i].applyForce(gravity);
        particleSystems[i].update();

		if (particleSystems[i].systemFade < 0) {
			particleSystems.erase(particleSystems.begin() + i);
		}
    }

this will remove the system, and i wasn’t seeing any problems when I was testing it out.
But I always learned that if you are iterating over a container while changing its contents (ie. removing them), then you should use an iterator. So if you would like to use an iterator instead, here is the code:

	auto iter = particleSystems.begin();
	while (iter != particleSystems.end()) {
		iter->applyForce(gravity);
		iter->update();

		if (iter->systemFade < 0) {
			iter = particleSystems.erase(iter);
		} else {
			iter++;
        }
	}

Also, I noticed that if you launch two (or more) fireworks before one of them turns into the particle explosion, (by this I mean, if you have two instances of the fireworks class traveling upwards) then the first one to reach the 50 height threshold gets turned into the particle system and the other firework instances “disappear”. This is because of how you are removing the firework instances from the firework vector. pop_back() removes the last element form the vector. So if you have two fireworks traveling upwards, firework[0] will reach the threshold first, calling firework.pop_back() removing firework[1] from the vector. You need to remove the element that reaches the threshold, so use firework.erase(firework.begin() + i); instead.

wow, sorry this response became so long!
hope this helps!
~Adam


#6

Super helpful again! Thanks Adam!