/* Clouds * by Erica Liszewski * November 4, 2007 * for DMST 3211 at University of Denver * * Generated Clouds ( bunches of circles ) that either * explode outwards ( right click ) or implode ( left click). * Colors are based on the area of the screen that is clicked. * * If left idle (no mouse interaction, and no clouds on the * screen) for 2 seconds, an idle animation will start showing * a ball that bounces around the screen creating Clouds. */ //holds all the active clouds CloudList clouds; //counts frames mouse has been down for int down_frames; //the framerate...because I use it for timing stuff int framerate; //for the idle animation stuff boolean idle; int idle_frames; Idler idler; /* void setup() * setup stuff */ void setup(){ //the basics background(0); size(600, 600); framerate = 30; frameRate(framerate); //create a new list of clouds clouds = new CloudList(); //start down_frames at 0 down_frames = 0; //start out with idle animation idle = true; //pretend we've been idle for 2 seconds //i.e. start doing idle stuff idle_frames = framerate*2; idler = new Idler(); } /* void draw() * handles the drawing */ void draw(){ if(mousePressed){ if (down_frames++ > (framerate/2) && down_frames%(framerate/3) == 0){ //create a new cloud if(mouseButton == LEFT) { Cloud temp = new Cloud(); //add it to the lis clouds.addCloud(temp); } else if(mouseButton == RIGHT){ Cloud temp = new ReversedCloud(); //add it to the lis clouds.addCloud(temp); } else if(mouseButton == CENTER){ int temp_num = round(random(1)); if(temp_num == 1) { Cloud temp = new Cloud(); //add it to the lis clouds.addCloud(temp); }else if (temp_num == 0){ Cloud temp = new ReversedCloud(); //add it to the lis clouds.addCloud(temp); } } } } //if now mouse interaction, see if there are any Clouds else if(clouds.isEmpty()) idle = true; //clear the backgroud background(0); //draw the clouds clouds.drawClouds(); //if nothing is happening on the screen, start the idler if(idle && idle_frames++ > (framerate*2)){ //add a new Cloud every half second if(idle_frames%(framerate/2) == 0){ idler.addCloud(clouds); } idler.render(); } } void mousePressed(){ idle = false; idle_frames = 0; if(mouseButton == LEFT){ //create a new cloud Cloud temp = new Cloud(); //add it to the lis clouds.addCloud(temp); } else if(mouseButton == RIGHT){ //create a new cloud Cloud temp = new ReversedCloud(); //add it to the lis clouds.addCloud(temp); } } /* void mouseReleased() * handles mouse clicks */ void mouseReleased(){ down_frames = 0; } /*private class Idler * a class that provides something interesting to watch if you * don't feel like clicking */ private class Idler{ int radius;//radius of the object Point center;//center of this object int x_veloc, y_veloc;//speed in each direction int my_red, my_green, my_blue; public Idler(){ radius = round(random(30, 40)); center = new Point (random(width), random(height)); x_veloc = round(random(-4,4)); y_veloc = round(random(-4,4)); } /*public void addCloud(CloudList c) * CloudList c - the CloudList to add a Cloud too * adds a cloud to the input CloudList at the current * location of the Idler */ public void addCloud(CloudList c){ int temp_num = round(random(1)); if(temp_num == 1) { Cloud temp = new Cloud((int)center.x, (int)center.y); //add it to the lis clouds.addCloud(temp); }else if (temp_num == 0){ Cloud temp = new ReversedCloud((int)center.x, (int)center.y); //add it to the lis clouds.addCloud(temp); } } /* public void render() * draws the Idler on the screen */ public void render(){ //recalculate the center center.x = center.x + (x_veloc); center.y = center.y + (y_veloc); if( center.x > width-radius){ center.x = width-radius; x_veloc = 0-x_veloc+round(random(-1,1)); } else if(center.x < 0+radius){ center.x = 0+radius; x_veloc = 0-x_veloc+round(random(-1,1)); } if( center.y > height-radius){ center.y = height-radius; y_veloc = 0-y_veloc+round(random(-1,1)); } else if(center.y < 0+radius){ center.y = 0+radius; y_veloc = 0-y_veloc+round(random(-1,1)); } //really boring if velocity is 0 in one direction, so not allowed if(x_veloc == 0) x_veloc = 1; if(y_veloc == 0) y_veloc = 1; //set color based on location my_green = round(norm(center.x, 0, width) * 255); my_blue = round(norm(center.y, 0, height) * 255); my_red = round(norm(abs(center.x-center.y), width-height, width) * 255); //setup to draw fill(my_red, my_green, my_blue, 255); smooth(); noStroke(); ellipseMode(RADIUS); //and draw ellipse(center.x, center.y, radius, radius); } } /* private class Cloud * creates and draws a cloud on the screen */ private class Cloud { Point center; //the center of the cloud float dist_from_start;//how many times it's moved from starting int x_veloc, y_veloc;//speed in each direction Wisp[] wisps;//array of wisps int num_wisps;//number of wisps in array boolean dead;//true if this cloud no longer has anything to display /* public Cloud() * creates a cloud at the location of the mouse, with a random * number of wisps, a random speed and direction */ public Cloud(){ //how many wisps we will have num_wisps = round(random(20, 40)); wisps = new Wisp[num_wisps]; for(int i=0; i width+radius || tempx < 0-radius || tempy > height+radius || tempy < 0-radius){ /* was for collision detection with the edge of the screen * but won't work for now if(tempx > width-radius || tempx < 0+radius || tempy > height-radius || tempy < 0+radius){ x_veloc = 0-x_veloc; y_veloc = 0-y_veloc; if( tempx > width-radius) tempx = width-radius; else if(tempx < 0+radius) tempx = 0+radius; if( tempy > height-radius) tempy = height-radius; else if(tempy < 0+radius) tempy = 0+radius; */ dead = true; } //if it's not visible, it's dead if(my_alpha <=0 ) dead = true; //setup to draw fill(my_red, my_green, my_blue, my_alpha); noStroke(); ellipseMode(RADIUS); //and draw ellipse(tempx, tempy, radius, radius); //increment distance for next time dist_to_cloud+=0.5; //decrease alpha my_alpha-=1; } /* public void reset() * setup stuff */ public void reset(){ // dist_to_cloud = 0.0; speed = random(0, 3); radius = round(random(5, 20)); x_veloc = round(random(-2,2)); y_veloc = round(random(-2,2)); } } /*provate class ReversedWisp * Wisps that move in towards the center point */ private class ReversedWisp extends Wisp{ /* public ReversedWisp() * creates a ReversedWisp with a random size, speed and velocity * and a color based off mouse location */ public ReversedWisp(){ my_alpha = 255;//full alpha my_blue = round(norm(mouseX, 0, width) * 255); my_red = round(norm(mouseY, 0, height) * 255); my_green = round(norm(abs(mouseX-mouseY), width-height, width) * 255); dist_to_cloud = my_alpha; dead = false; reset(); } /* public ReversedWisp(int x, int y) * int x - the x value of the center of the cloud * int y - the y value of the center of the cloud * creates a Wisp with a random size, speed and velocity * and a color based off input x and y */ public ReversedWisp(int x, int y){ my_alpha = 255;//full alpha my_blue = round(norm(x, 0, width) * 255); my_red = round(norm(y, 0, height) * 255); my_green = round(norm(abs(x-y), width-height, width) * 255); dist_to_cloud = my_alpha; dead = false; reset(); } /* public void render(Point center) * Point center - the current center of the cloud this belongs to * draws a Wisp on the screen */ public void render(Point center){ if(dead) return; //if dead, skip all this //figure out new center of wisp float tempx = center.x + (x_veloc * dist_to_cloud * speed); float tempy = center.y + (y_veloc * dist_to_cloud * speed); //if it's not visible, it's dead if(my_alpha <=0 ) dead = true; //setup to draw // colorMode(HSB, 255); fill(my_red, my_green, my_blue, my_alpha); noStroke(); ellipseMode(RADIUS); //and draw ellipse(tempx, tempy, radius, radius); //increment distance for next time dist_to_cloud-=1; //decrease alpha my_alpha-=1; } } /* private class Point * more of a struct, just holds x and y values */ private class Point{ public float x, y;// x and y of point /* publiv Point(float x, float y) * float x - x value of point * float y - y value of point * creates a point with input x and y */ public Point(float x, float y){ this.x = x; this.y = y; } } /*private class CloudList * a linked list of CloudNodes */ private class CloudList{ CloudNode head;//head of list /* public CloudList() * creates an empty CloudList */ public CloudList(){ head = null; } /* public boolean isEmpty() * returns true if List is empty, false otherwise */ public boolean isEmpty(){ if (head == null) return true; else return false; } /* public void addCloud(Cloud c) * Cloud c - the Cloud to be added * adds the input Cloud to the list */ public void addCloud(Cloud c){ // println("adding a cloud"); //create a new CloudNode CloudNode temp_node = new CloudNode(c); //if this is the only item if(head == null){ head = temp_node; return; } else{//there are other clouds in the list already temp_node.next = head; head = temp_node; } } /* private void removeCloud(CloudNode cn) * CloudNode cn - the CloudNode of the Cloud to be removed * removes the CloudNode specified */ private void removeCloud(CloudNode cn){ // println("removing a cloud"); if(cn == head){//if this is the only cloud head = cn.next; } else{//there are other clouds cn.last = cn.next; if(cn.next != null) cn.next = cn.last; } } /*public void drawClouds() * runs through the list and tells each Cloud to draw * also removes any dead Clouds */ public void drawClouds(){ //get the head CloudNode temp_node = head; while( temp_node != null){//while we have node //check if it'd dead, and remove if needed if(temp_node.cloud.dead) removeCloud(temp_node); //render else temp_node.cloud.render(); //increment temp_node = temp_node.next; } } } /* private class CloudNode * a node for the CloudList * holds a Cloud */ private class CloudNode { Cloud cloud;//the cloud CloudNode next, last;//links to next and last nodes in list /* public CloudNode(Cloud cloud) * Cloud cloud - the cloud for this CloudNode to hold * creates a CloudNode with the input Cloud */ public CloudNode(Cloud cloud){ this.cloud = cloud; next = null; last = null; } }