Rock-paper-scissors, in a box.
A visual exploration of “Rock-paper-scissors” dynamics within a particle system.
produced by: Samuel Nunez
“Some bacteria exhibit a rock paper scissors dynamic when they engage in antibiotic production. The theory for this finding was demonstrated by computer simulation and in the laboratory by Benjamin Kerr, working at Stanford University with Brendan Bohannan. Biologist Benjamin C. Kirkup, Jr. demonstrated that rock paper scissors dynamics allowed for the continued competition among bacteriocins.” (Wikipedia)
Concept and background research
The concept for this project only settled with time as I wrapped my head around different ideas - I admittedly had no clue what it might be when I started working on this. The project originally started off as my first attempt at programming a simple video-game back in November. The original idea was to control the movement of a Voronoi cell amongst its neighbors: The closer it would get to another cell, the harder it should get to move around, forcing the player to move around the edges. I originally coded this by simply reducing velocity proportionally to the distance to the closest cell, but this didn't work as I thought it would: neighboring cells felt “sticky”, and it was annoying to move around, so I realized I had to work with forces - This became the building block behind what would end up becoming a particle system.
Parallel to this, I was inspired by Conaway’s Game of Life and similar examples where autonomous behavior arises from a set of simple rules. The final concept eventually settled and revolves around the idea of "rock-paper-scissors" logic, the way it generates continuous movement, and the formations that come with it.
The particle system works as follows: There are three kinds of particles, each of which is attracted by the next one. The three kinds of particles consequently follow each other in a rock-paper-scissors dynamic, creating constant movement and avoiding still arrangements. If the force is inverted, the attraction is turned into repulsion and the movement dynamic is more prone to result in still arrangements as particles group together with their equals. I additionally created a further rule in order to encourage constant movement (if desired) when the force is inverted, whereby one of the “species” of particles follows another in addition to the rock-paper-scissors dynamic explained above. Part of the beauty of it is that each time I run the program different formations arise, so I am always surprised by what the program comes up with on each run. However, by creating a timeline that alters parameters such as force intensity, force-field radius, "gravity" (force towards the center), etc. I was able to create a rough narrative that showcases many of the different formations, patterns, or visuals I found interesting.
I encountered various challenges during the development of the program which got me to understand the importance of different program design paradigms, as well as the need for simple code that makes use of the least amount of resources possible. This came as I tried to add the third and final force in order to complete the 3-way dynamic and started to encounter constant bugs: I realized I was losing my grip on the logic of the program so I had no way of understanding the problems. I was originally using large 2-dimensional arrays to store various value calculations as global variables, instead of using local primitive variables inside for loops, therefore saving on memory and simply making things easier to understand. Whereas I had originally envisioned a program following an OOP logic, I realized I had either not done it properly or it simply wasn’t the way to go in the case of this program (probably the former!). In any case, after a couple of days of frustration, I decided to start the whole project from scratch to see if that cleared things in my head. It definitely did: I greatly reduced the amount of code by placing most calculations inside the same function & for loop (therefore ditching the OOP paradigm), got rid of a bunch of unnecessary arrays, and managed to solve problems much faster as the logic was simpler. It was also eye-opening to see how much of the problems I had on my first program came down to the order of calculations: I got rid of a couple of bugs by rearranging the order of functions inside the update() function.
The crux of the code comes down to the calculation of the distances between all particles, finding the closest points, and applying the corresponding forces between them. Here is how I ended up doing it:
As I don’t have much knowledge of basic physics, by far I found the hardest part of the project was getting the particles to repel in the right direction (that is, directly opposite of the direction between the two particles at question). I ended up doing it in what is probably a very over complicated way, but it worked: (screenshot of my confused notes included)
Another problem I encountered was that the movements could get very jittery. To tackle this I created a “value stream smoother” class, inspired by the smooth/slide object in Max/MSP. It works by constantly adding to the “smoothed” value a fraction (the "slide factor") of its difference to the original value, so that it is constantly following the original value
One of the main things I would want to work on is to make the program a bit more efficient. It currently starts dropping below 30fps at around 1500 particles of each kind, and although that's probably a lot of computing, I'm sure my programming skills haven't allowed for the best efficiency.
On the visual side of the project, I think there is much to work on to make the graphics more engaging, such as making the trails join properly (instead of seeing a line made of disconnected points). Shaders would be an ideal way of making the project more interesting visually without overwhelming the CPU, although from what I’ve read I don’t think GLSL can take in so much information for every particle. Even so, I am curious to see what some photoshop-style filtering would come up with.
I feel like time-management was the main issue I've had during this project. I spent way too much time on the particle system itself and left only a few days to make it work as a visually engaging, projection-mapped piece. With a bit more time, I could have solved worked around a few problems I had with the scene manager that meant I couldn't always do what I wanted. (the program kept crashing when I pressed 7 to clone a preset).
Also please note that as the computer was a bit overwhelmed when recording, the screen capture skips quite a lot of frames so the video is not as smooth as it should be.
I wrote all of the code from scratch, except for this (for some simple color gradients) https://forum.openframeworks.cc/t/background-gradient/1304
(Naturally I googled some basics such as how to get the minimum value of an array, but I dont have any more references as such as I didnt copy or transform any code)