We are about to switch to a new forum software. Until then we have removed the registration on this forum.
Hello!
I'm going to try to get the gist of my problem across without having to paste a novel. I'm using 2 classes, one called Emitter and one called Particle. Each Emitter emits Particles, instantiating a new Particle and appending it to a Particle ArrayList every n number of frames. Each draw() cycle, the Emitters iterate through all of the Particles and call their .update() and .display() functions.
Everything was working as expected until I tried to make the individual Particles fade out over time. Here are the display and update methods from the Particle class;
void display() {
pushMatrix();
strokeWeight(strokeWeight);
translate(position.x, position.y);
stroke(colorVals[0], colorVals[1], colorVals[2], colorVals[3]);
point(0, 0);
popMatrix();
t++;
}
void update() {
colorVals[3] -= 5;
position.add(velocity);
if(friction > 0) {
position.mult(friction);
}
}
Unfortunately, when I try to use this in conjunction with an Emitter, I can't get individual Particles to fade out after they've been emitted. Instead, the Emitter just emits particles with a lower and lower alpha value until none of the Particles being emitted are visible. Here's the Emitter.display method that loops through the Emitter's List Array:
void display() {
if(particles.size() > 0) {
for(i = 0; i < particles.size() - 1; i++) {
Particle particle = particles.get(i);
if(particle.position.x > (width / 2) || particle.position.x < (width / -2)) {
particles.remove(i);
}
if(particle.position.y > (height / 2) || particle.position.y < (height / -2)) {
particles.remove(i);
}
pushMatrix();
translate(position.x, position.y);
particle.update();
particle.oscillate();
particle.draw();
popMatrix();
}
}
}
Can anyone help me achieve the desired result of each Particle fading out at its own rate after it is emitted? If more code is needed to track down the problem, I'd be happy to provide more. Just didn't want to paste too much code. Thanks in advance!
Answers
Doesn't a Particle have an initial value for colorVals[3] when it's instantiated?
Or don't you tell me that colorVals is a "global" sketch's field rather than Particle's! @-)
It does have an initial value set for colorVals[3], and I'm making change to a member variable of Particle called colorVals. So yes they do and no there isn't a global sketch field called colorVals. These code snippets are part of classes. I didn't post all of the code for each class, but I mentioned it in the post. Let me know if you need me to post the whole class.
Well, colorVals[3] is the alpha value. The way you put it makes me believe that Emitter ends up instantiating Particle objects w/ colorVals[3] already 0 or less after some time! It doesn't make any sense for me, sorry!
Anyways, as extra reference, here's an online example which got an "oversëer" class which instantiates 3 subordinates. Very similar to yours I guess:
http://studio.processingtogether.com/sp/pad/export/ro.9lTJ6qSlmCidk/latest
Hmm, I think that is what is happening. I'll investigate further. I think I accidentally accepted these answers, is there a way to undo that since the question is still open? Thanks!
After some looks at Emitter's display() method, inside the for loop...
I've spotted a classic bug: we can't use remove() for a List, unless it's backwards!
Take a look at my WaveTrio's script() method. It shows the simplest backwards loop technique for List remove()!
While at sketch's draw()'s own loop, a more efficient technique is used! \m/
P.S.: Even us moderators can't undo it, sorry! :-&
Thanks GoToLoop! I tried doing it this way, but got a syntax error due to the for loop syntax. I understand the loop, as I've used something similar in other languages, but I am not very familiar with Java. Anyway, I was able to change the loop slightly and get it working using your technique. Much appreciated! Can you explain what is going on that requires this? Thanks again!
The updated code:
That is not restricted to Java. It's how an ordered List is internally organized!
When a remove() is issued, all indices to its right is left-shifted.
All of a sudden, the next index becomes the current index!
So at the next loop index iteration, it ends up skipping that 1!
A backwards loop fully avoids that problem, b/c indices before the index being removed don't incur any shifting!
Actually, we can use regular forward loops too, as long as we decrease the iterator after the remove()! :P
Can you please try this 1 out and see whether it still works for ya? ;;)
And I believe this version would be a lil' faster too:
GoToLoop! Thank you! I realized the problem with my syntax was leaving out the second semicolon in the for loop! Now I have your original code working. Also, thank you for the optimization and explanation! Problem solved, thanks so much!