Generative art experiment 4: colourful roots
February 26, 2013
It’s been a while since I’ve posted about anything interesting that I’ve made in Processing. Time to put an end to that! Allow me to present “colourful roots”. It started off as a simple particle system with the usual fade effect, but when I let the particle shrink and stay fully opaque, I was delighted to see what it looked like!
The processing code
// canvas colour
int background_color = color(70, 70, 70);
// particle colours
color[] colors = {
color (227, 211, 31), // yellow
color (227, 31, 123), // pink
color (31, 188, 227) // blue
};
// colour of the stroke around the particles
color stroke_color = color(0, 70); // black, 70% alpha
// should the mouse draw particles when moved?
Boolean INTERACTIVE = true;
// should the canvas be cleared on each particle iteration
Boolean CLEAR = false;
//-----------------------------------------------------------------//
//-----------------------------------------------------------------//
//-----------------------------------------------------------------//
//-----------------------------------------------------------------//
ArrayList particles;
// reset on mouse click
void mouseClicked () {
setup();
mouseMoved();
}
// save on press spacebar
void keyPressed () {
if (keyCode == RETURN || keyCode == ENTER) {
save("Colourful entrails " + year() + "-" + month() + "-" + day() + " " + hour() + ":" + minute() + ":" + second() + ".png");
}
}
// add particles on mouse move
void mouseMoved () {
if (!INTERACTIVE) return;
int count = int(random(2, 5));
while(count-- > 0) {
addParticle(new PVector(mouseX, mouseY));
}
}
void setup() {
size(800, 400, P2D);
blendMode(ADD);
stroke(stroke_color);
background(background_color);
particles = new ArrayList();
// create a particle which'll go around making particles if it's not interactive
if (!INTERACTIVE) {
Particle generator = new Particle(new PVector(width/2, height/2));
generator.size = 10000;
while(generator.isAlive()) {
int count = int(random(2,5));
generator.update();
while (count-- > 0) {
addParticle(generator.position);
}
}
}
}
// add a new particle to the particles arraylist with specified position
void addParticle (PVector position) {
// clone the vector
PVector position_clone = new PVector(position.x, position.y);
particles.add(new Particle(position_clone));
}
void draw() {
// keep track of dead particles - they'll be removed after the loop
ArrayList dead = new ArrayList();
if (CLEAR) {
fill(background_color);
rect(0, 0, width, height);
}
// go through each of the particles and update/draw
ListIterator it = particles.listIterator();
while (it.hasNext()) {
Particle particle = (Particle) it.next();
// only draw if it's alive
if (particle.isAlive()) {
particle.update();
particle.draw();
} else { // otherwise add to dead list
dead.add(particle);
}
}
// remove all dead particles
particles.removeAll(dead);
}
// a tad messy, building it up as i go along
class Particle
{
PVector position;
PVector velocity;
PVector force;
float size;
color c;
int life;
Particle (PVector p) {
life = 0;
position = p;
size = random(30, 50);
velocity = new PVector(random(2, 5), 0);
rotate2D(velocity, random(0, TWO_PI));
c = colors[int(random(colors.length))];
force = new PVector(0, 1);
}
void update () {
life++;
if (life == 20) {
velocity.mult(1.1);
}
if (life < 20) {
size *= 0.99;
} else {
size *= 0.95;
}
position.add(velocity);
velocity.rotate(random(-QUARTER_PI, QUARTER_PI));
}
void draw () {
pushMatrix();
translate(position.x, position.y);
fill (c);
ellipse(0, 0, size, size);
popMatrix();
}
Boolean isAlive() {
return size >= 1;
}
}
void rotate2D(PVector v, float theta) {
float xTemp = v.x;
v.x = v.x*cos(theta) - v.y*sin(theta);
v.y = xTemp*sin(theta) + v.y*cos(theta);
}