// boom(untitled)(web version) // mitchell whitelaw - april 2006 int numBits = 80; int cloudRadius = 300; // float gravity = 0; float friction = 0.999; float velFloor = 0.02; // the lower limit for velocity: stop drawing when things get this slow float distanceCeiling = 1000; // stop drawing when things get this far from the origin color bgcolour = color(255,255,255); // float distancefactor = 10000; // int drawing = 0; int totalDrawing = 0; float fadeAlpha = 1; int originX; int originY; int cloudX; int cloudY; Particle[] theCloud; // the array of particles void setup() { size (900,550); background(255); smooth(); //noFill(); makeCloud(); } void makeCloud() { theCloud = new Particle[numBits]; for (int i=0; i < numBits; i++){ float radius = ((i+1)/float(numBits))*cloudRadius; float angle = random(TWO_PI); float xPos = cloudX + (radius*sin(angle)); float yPos = cloudY + (radius*cos(angle)); theCloud[i] = new Particle(xPos,yPos,0,0,i,0,0,0,0,0); // x, y, xvel, yvel, particle ID, neighbour1id, neighbour2id, neighbour1distance, neighbour2distance, drawingFlag } } class Particle { int id; // particle ID float x; // x position float y; // y position float xvel; // x velocity float yvel; // y velocity int myNeighbour; // ID of my neighbour int myNeighbour2; float neighbourDistance; // distance to my neighbour float neighbourDistance2; int drawingFlag; // 1 = drawing, 0 = not Particle(float xIn, float yIn, float xvelIn, float yvelIn, int idIn, int myNeighbourIn, float neighbourDistanceIn, int myNeighbourIn2, float neighbourDistanceIn2, int drawingFlagIn) { // particle constructor x = xIn; y = yIn; xvel = xvelIn; yvel = yvelIn; id = idIn; myNeighbour = myNeighbourIn; myNeighbour2 = myNeighbourIn2; neighbourDistance = neighbourDistanceIn; neighbourDistance2 = neighbourDistanceIn2; drawingFlag = drawingFlagIn; } void moveParticle(){ x += xvel; // add xvel to xpos y += yvel; // add yvel to ypos xvel = xvel*friction; // factor in friction yvel = yvel*friction + gravity; // and gravity for y axis } void findNeighbour(){ int theNeighbour = 0; // id of my nearest neighbour int thenextNeighbour = 0; // id of my second-nearest neighbour float minDistance = 10000; // make it a high number so we can find the minimum float nextminDistance = 10000; float theDistance = 0; for (int i=0; i < numBits; i++){ theDistance = sqrt(sq(x - theCloud[i].x) + sq(y - theCloud[i].y)); // distance from me to each of the others if (theDistance < minDistance && theDistance > 0){ // if the distance is less than the lowest yet, and more than 0 (ie it's not the distance from me to me). minDistance = theDistance; theNeighbour = i; } if (theDistance < nextminDistance && theDistance > minDistance){ nextminDistance = theDistance; thenextNeighbour = i; } } myNeighbour = theNeighbour; // the ID of the neighbour particle neighbourDistance = minDistance; // distance from me to my neighbour myNeighbour2 = thenextNeighbour; neighbourDistance2 = nextminDistance; } void goBoom(){ originX = mouseX; originY = mouseY; float xOffset = x - originX; float yOffset = y - originY; float thisDistance = sqrt(sq(xOffset) + sq(yOffset)); float absOffset = abs(xOffset) + abs(yOffset); float xRatio = xOffset/absOffset; // ratio of x/y - using abs to maintain sign of offset float yRatio = yOffset/absOffset; // ratio of y/x xvel = distancefactor*xRatio*(1/sq(thisDistance)); // the initial X velocity yvel = distancefactor*yRatio*(1/sq(thisDistance)); // the initial Y velocity drawing = 1; } void drawParticle() { float originDistance = sqrt(sq(x-originX) + sq(y-originY)); if (drawing == 1 && (abs(xvel)+abs(yvel)) > velFloor && originDistance < distanceCeiling) { drawingFlag = 1; stroke(55,1); line(x,y,theCloud[myNeighbour].x,theCloud[myNeighbour].y); stroke(85,2); line(theCloud[myNeighbour].x,theCloud[myNeighbour].y,theCloud[myNeighbour2].x,theCloud[myNeighbour2].y); stroke(22,2); line(theCloud[myNeighbour2].x,theCloud[myNeighbour2].y,x,y); } else { drawingFlag = 0; } } } void keyPressed(){ if (key == 'b') { drawing = 1; fadeAlpha = 1; for (int i = 0; i < numBits; i++){ theCloud[i].goBoom(); // all go boom } } else if (key == 'c') { background (bgcolour); drawing = 0; } else if (key == 'r') { cloudX = mouseX; cloudY = mouseY; makeCloud(); // remake the cloud } } void draw(){ int countDrawing = 0; for (int i=0; i < numBits; i++){ theCloud[i].findNeighbour(); theCloud[i].drawParticle(); theCloud[i].moveParticle(); countDrawing += theCloud[i].drawingFlag; } totalDrawing = countDrawing; if (totalDrawing == 0){ fill(255,255,255,fadeAlpha); stroke(255,255,255,fadeAlpha); rect(0,0,width,height); fadeAlpha = fadeAlpha * 1.02; } }