/*------------------------------------------------------------------------------------------------------------------------ SnowFlares, by David Murphy January 2008 This is an interactive animation of falling snow lit only by a mouse flashlight, with the user being able to interrupt the peace and tranquility with Flares, which will light the snow appropriately. The middle mouse button drops a flare, the left button increases the wind speed, and the right button decreases the wind speed (the speed can go negative, switching the direction of the wind). TO DO: -This is fairly processor intensive - Find a way to make it more efficient. -Make each flare have its own color, instead of all red. -Tinge the flakes and ground based on the color ofthe object lighting it. --------------------------------------------------------------------------------------------------------------------------*/ //specify number of flakes, flares, ground pieces in animation int numFlakes = 200; int numFlares = 5; int numGround = 160; //create arrays for them SnowFlake[] theflakes = new SnowFlake[numFlakes]; Flare[] theFlares = new Flare[numFlares]; //three rows of ground parts GroundPart[] theGround0 = new GroundPart[numGround]; GroundPart[] theGround1 = new GroundPart[numGround]; GroundPart[] theGround2 = new GroundPart[numGround]; //these variables control how fast the flares fall and the wind speed, as well as providing counters for varius functions. int fallSpeed = 3; int framecounter = 0; int counter = 0; //true = right, false = left boolean dir = true; float windSpeed = random(1); void setup(){ size(800,600); background(0); //create snowflakes at random places on screen to begin. //From here, the draw function will make them "float" down for(int i=0;i= 100) framecounter = 1; else framecounter++; background(0); //draw and update Flares - float down like the flakes for(int i=0;i= theFlares.length-1) counter = 0; else counter++; } } //this is the snowflake class which keeps track of all the snowflakes' positions, directions, and sizes. class SnowFlake { float xpos, ypos, xdir, ydir, radius, distance; //constructor SnowFlake(float x, float y){ xpos = x; ypos = y; xdir = windSpeed; ydir = random(3); radius = random(0.5,5.0); distance = dist(xpos,ypos,mouseX,mouseY); } //this function simply draws the flake in white at its position: (xpos,ypos), with color determined by distance from the //nearest light source (flare or mouse). void drawFlake(){ float white = 230 + (25 - 1.5*distance); //float tinge = white - distance/10; stroke(white,90); strokeWeight(2); fill(white); ellipse(xpos,ypos,radius,radius); } //this is the real meat behind this class - changes the snowflake's position to make it float down and //also pops them back to the top of the screen when they go off the bottom. void update(boolean d){ //update x position (the boolean is an artifact from previous version of code - //too complicated to remove it right now so it does nothing. This chunk will always increase the xpos if(d) xpos += windSpeed; else xpos -= windSpeed; //update y position ypos += ydir; //distance to current mouse location float theDist = dist(xpos,ypos,mouseX,mouseY); //check proximity to Flares for(int i=0; i < numFlares; i++) { //the "- theFlares[i].radius" makes bigger flares have a larger illumination radius float tempDist = dist(xpos,ypos,theFlares[i].xpos,theFlares[i].ypos) - theFlares[i].radius; if (tempDist < theDist) theDist = tempDist; } //update distance distance = theDist; //Make sure it wraps around when a flake goes off the screen if(xpos >= width - radius){ xpos = radius; } if(xpos < radius) xpos = width - radius; if(ypos >= height - radius){ ypos = radius; //placed at random position at the top if it goes off the bottom xpos = random(radius,width - radius); } } } //class for the Flares which will pop up when the mouse is pressed. class Flare { float xpos,ypos,radius; //default constructor (places flares off the viewing screen. They will be replaced later when the use adds a Flare Flare(){ xpos = -1000; ypos = -1000; radius = random(1); } //specified constructor (used when user presses middle mouse button to create Flare) Flare(float x, float y) { xpos = x; ypos = y; radius = random(10,50); } //draws the flare with strokeWeight "rad" - this allows for dynamic stroke weight which makes the flare flicker void drawFlare(float rad){ stroke(255,0,0,90); strokeWeight(rad); //println(rad); fill(255,0,0,95); ellipse(xpos,ypos,radius*2,radius*2); fill(255,255,255); stroke(255,255,255,95); ellipse(xpos,ypos,radius,radius); } //update position of flare and make it stop when it hits the ground, then dissapear. void update(){ //if it hits ground, sit for awhile then "disappear" (gets moved off the viewable window) if(ypos >= height - 25 - radius/2){ if(framecounter == int(random(1,100))){ xpos = -1000; ypos = -1000; } } else{ ypos += fallSpeed; //Flares are now affected by wind as well, but only half as much as the snow xpos += windSpeed/2; } } } //class to hold Ground segments and light them correctly based on distance to light objects such as flares class GroundPart { float xpos, ypos, distance; //default constructor. not used atm. GroundPart() { xpos = -1000; ypos = -1000; distance = dist(xpos,ypos,mouseX,mouseY); } //specified constructor GroundPart(float x, float y) { xpos = x; ypos = y; distance = dist(xpos,ypos,mouseX,mouseY); } //draws the square, color based on lighting distance void drawGroundPart() { float white = 230 + (25 - 1.5*distance); stroke(white,90); strokeWeight(5); fill(white); rect(xpos,ypos,10,8); } //update distance to update lighting later when drawn void update() { float theDist = dist(xpos,ypos,mouseX,mouseY); //check proximity to Flares for(int i=0; i < numFlares; i++) { //the "- theFlares[i].radius" makes bigger flares have a larger illumination radius float tempDist = dist(xpos,ypos,theFlares[i].xpos,theFlares[i].ypos) - theFlares[i].radius; if (tempDist < theDist) theDist = tempDist; } //update the distance distance = theDist; } }