# Nipple Congress Dwelling the unique constraints and opportunities presented by the .gif format, I had the idea to generate a pattern, and to then use that pattern as a seed for a particle system. As it turned out, this pattern-as-seed plan was pretty convoluted. My pattern held its own aesthetically, and there was no need to abstract it further. At this point, the difficulty was to animate the pattern in a seamless fashion. Golan helped me formulate a solution, which entailed gradually shifting initial velocities according to trigonometric relationships.

I think the .gif succeeds in its playful treatment of stability and instability: the nipples are effectively stationary, where the arm-tentacles twitch and/or undulate erratically. Generally speaking, the experience of the .gif changes dramatically from region-to-region. Maybe this lack of focus is a drawback, and if so, I could improve the piece by unifying it visually. It might also benefit a clarified kinetic gestalt, or put in other words: buttery, logical motion. (Or its charm could lie in the jerky crudeness.)

(As a side note, the edicts of my Nipple Congress have strong ties to those of Jared Tarbell’s Substrate, since a nearly identical branching rule governs the spatial aspect of the forms generated onscreen. )

```GridParticle[] gP = new GridParticle;
int seed = 10;
PVector texture;

void setup() {
size(600, 400);
randomSeed(seed);
noiseSeed(seed);
initGrid();
smooth();

background(0,4,118);
}

void initGrid() {
for (int i= 0; i  < gP.length; i++) {
gP[i] = new GridParticle(i);
}
}

void draw() {
background(0,4,118);
randomSeed(seed);
noiseSeed(seed);
initGrid();
for (int n = 0; n < 1400; n++) {
for (int i= 0; i  < gP.length; i++) {
gP[i].update();
gP[i].drawMe();
}
}
filter(INVERT);
saveFrame();
}

class GridParticle {
PVector pos;
PVector vel = new PVector(0, 1);
float strokeW;
int changedThresh;
int stroke = 235;

strokeW = 5;
changedThresh = int(random(0, 10));
pos = new PVector(random(width*.2, width*.8), random(height*.2, height*.8));
float randomAngle = random(HALF_PI);
float frameBasedAngle = map(frameCount % 10000, 0, 9999, 0, TWO_PI);
vel.x = randomRadiusX * cos(randomAngle + frameBasedAngle);
vel.y = randomRadiusY * sin(randomAngle + frameBasedAngle);
}

void update() {

stroke*=.87;

float yNoise = map(noise(vel.y/100.0), 0,1, -.002, .002);
vel.y += yNoise;

if (pixels[floor(width*int((pos.y + 5) % height) + int(pos.x))] != color(0,4,118) ||
pixels[floor(width*int((pos.y) % height) + (int(pos.x + 5) % width))] != color(0,4,118)) {
strokeW *= .985;

vel.x *= -1;
}

pos.x = abs((pos.x + vel.x)) % width;
pos.y = abs(pos.y + vel.y) % height;
}

void drawMe() {
float vary = noise(pos.x/10.0, pos.y/10.0)*4;
strokeWeight(strokeW * vary);

float blink = map((frameCount + blinkOffset) % 10, 0, 9, 0, 1);