I mentioned in my last post about VizTech2 (my P5.js course, with Pedro Cruz) that we had learned how to make a fireworks display using particle systems. At first, the sketch made fireworks when you clicked with the mouse.
Then, we taught it to generate new fireworks by implementing a “lifetime” for each particle. If too many particles had “died,” a new set was created at the location of the last particle to die. Adding “gravity” and color effects also made things seem more realistic.
Then, we switched from a mouse-click event to a click and drag event, so that your mouse cursor left a trail of fireworks behind it as you dragged. That one was a little like drawing with sparklers in the air on the 4th of July.
To that, we added an attractor: a single point that exerts a “force” on each particle and pulls them into it.
Adding a few of these attractors in a row produced really beautiful results (the red dots are attractors).
From this base functionality, I started to expand into topics we haven’t covered in class, but that are very clearly explained in the Nature of Code. I have to translate the examples from Processing to P5.js, but the languages are so similar that that’s not too difficult.
In the class examples, we had only one kind of particle and one kind of attractor. I added a second kind of particle, and a second kind of attractor. I wanted to figure out how polymorphism and inheritance work, so I implemented child classes in my code, even though they’re not really necessary for such a simple application. I hope to keep working on this project on the side, so I wanted to leave plenty of room for expansion as I continue working my way through the book.
I gave each attractor a random strength (within a specified range), and used it to scale the circles, so that they’re all different sizes. Because the strength updates with each screen cycle, the bubbles grow and shrink in size. I also added a randomly oriented acceleration vector at each update, which allowed the attractors to wander around the screen during the course of the animation. Of course, this meant that I also needed to prevent them from leaving the screen entirely, so I added some code to make them bounce back off the edges and into the canvas.
I went back to the routine for adding particles on mouse click, but also included the auto-generate function to make sure that new particles were born as others died. Each generation event creates both kinds of particles in a 50/50 mix, and the number of particles and attractors scales based on screen size (this ensures that the screen doesn’t get too crowded or too empty to be interesting if you view it on a monitor of a different size).
I also added a “steering force” to the purple particles, which was supposed to make them “want” to travel toward the center of the screen. This first attempt at programming autonomy didn’t seem to do much, other than create an invisible “attractor” at the center of the screen.
The arrangement of attractors actually did a whole lot more to give the particles “behavior” than my deliberate programming did. I was surprised how often the particles followed one another around the screen, seeming to show primitive flocking behavior without any intervention on my part.
I’m still looking forward to teaching my particles to avoid each other when an attractor is too crowded, and I might play around with allowing attractors to switch types, too. But for now, I’m enjoying watching my little particles swim around on the screen. It’s almost a bad thing for them to be so interesting to watch…sometimes I end up just staring at the animation when I’m supposed to be writing code!
Here’s a still image of what the particles look like, but for the full effect you should go here and check them out for yourself.