Jump to Content

RSS Feeds:

Posts | Comments

http://ivanwlam.com/experiments/programming

Leave a Reply


Example

The actual example tends to crashes the applet on the web, so Go here to see the entire animation without applet crashes. an example of the first 100 of 1500-2000 flies flying to their positions. The applet may or may not slow your computer down for the duration. Sorry about that.

Processing Code in Example

 import processing.opengl.*; //required for placing text as shapes.    PGraphics img;  PImage flyImg;  color[] origPixels;  PFont font;  Fly[] flies = new Fly[0];  int numFlies;  int numSteps;  int sizeScale;  float flyDefaultWidth;  float flyDefaultHeight;  float fontHeight;    void setup(){   sizeScale=2;   size(500,500,OPENGL);   frameRate(500);   flyDefaultWidth=7.5*sizeScale;   flyDefaultHeight=10*sizeScale;   fontHeight=125*sizeScale;     numFlies=2000;   numSteps=40;     //load the image   flyImg=loadImage("fly.png");   //set it as center   imageMode(CENTER);       //The text   //get the character set so the font isn't loading the entire set of characters   // char[] charset={'F','L','Y'}; // only used if creating Font from a list from a computer   // font=createFont("Franklin Gothic Demi",fontHeight,false,charset); // only works if you computer has that exact font.   font=loadFont("FranklinGothic-Demi-48.vlw"); // only the letters F,L,Y are in the file to minimize file size.   textFont(font,250);   // textMode(SHAPE); //turns out textMode doesn't need to be set as SHAPE to detect pixels   fill(0,128,255);   textAlign(CENTER);   text("FLY",width/2,height*4/5); //write the text horizontally centered, and near the bottom of the window     //set up array and store the pixels on the window, including the text   origPixels=new color[width*height];   loadPixels();   for(int i=0;i<width*height;i++){   origPixels[i]=pixels[i];   }     //wipe the window clean so viewer won't see the text when the applet starts.   background(255);    }    void draw(){   //old test to draw all the possible places that is not occupied by the text based on the values collected in an array   // fill(255,0,0);   // stroke(255,0,0);   // for(int i=0;i<img.width*img.height;i++){   // if(origPixels[i]!=-16744193){   // point(i%img.width,floor(i/img.width));   // }   // }     //run the fly stuff only if there are still flies to be created and moved   if(frameCount<numFlies+numSteps){   //clear screen to draw the flies in new positions.   background(255);     //if not all the flies exist yet, create them, one by one.   if(flies.length<numFlies){   flies=(Fly[]) expand(flies,flies.length+1);   flies[flies.length-1]=new Fly();   }     //run through all the existing flies, and display them in new positions and add tints to them.   for(int i=0;i<flies.length;i++){   flies[i].move();   flies[i].display();   }   }   else {   //if all the flies are there, stop the loop so it doesn't draw anymore.   println("all done");   noLoop();   }  }    /*old test to check that the text is reading color   void mouseClicked(){   // println("Clicked on: "+mouseX+", "+mouseY);   // color origPix=origPixels[mouseY*img.width+mouseX];   // if(origPix==-16744193){   // print(" Not here.");   // }   // else {   // print(" Here okay.");   // }   } /**/    //create a fly class  class Fly{   float startX;   float startY;   int endX;   int endY;   float tempX;   float tempY;   //for old way of rotating only   // float newTempX;   // float newTempY;   float speedX;   float speedY;   float tempRotRad;   float rotRad;   int index;   float flyTintVal;   float flyScale;     Fly(){   //get starting position   //get X between -width/2 and width+width/2   startX=round(random(0-width/2,width*1.5));   //depending on where X is, Y may have a limited range to be.   //if X is not between 0 and width, Y can be anywhere from -height/2 to height+height/2   if(startX<=0 || startX>=width){   startY=round(random(0-height/2,height*1.5));   }   else {   //but if X is between 0 and width, Y can only be before -height/2 and after height+height/2   startY=round(random(-0.4,1.4))*height;   }     //get the end position   do{   endX=round(random(0,width-1));   endY=round(random(0,height-1));   index=endY*width+endX;   }   //if the pixel index of the end position lands on a point that is occupied by the text, get the number again.   while(origPixels[index]==-16744193);     //determine how many pixels it moves per step.   speedX=(endX-startX)/numSteps;   speedY=(endY-startY)/numSteps;   //the speed determine the direction, and therefore rotation of the image to make it look like it's flying head on instead of sideways   tempRotRad=atan(speedY/speedX);     //here's the mind-exploding part. using radians, determine which quadrant the image should be facing, then rotate the image.   //BUT, instead of starting on the right, quadrant counting starts at the top, since the image points at the top.   //BUT, the angle that the speed is measure remains relative to the x-axis, so the math to get the correct angle is different.   //if landing on quadrants:   if(speedX>0 && speedY>0){   rotRad=((PI)/2)+tempRotRad;   }   else if(speedX<0 && speedY>0){   rotRad=(-PI)/2+tempRotRad;   }   else if(speedX<0 && speedY<0){   rotRad=(-PI)/2+tempRotRad;   }   else if(speedX>0 && speedY<0){   rotRad=(PI)/2+tempRotRad;   }   //if landing on axis:   else if(speedX>0 && speedY==0){   rotRad=PI/2;   }   else if(speedX==0 && speedY>0){   rotRad=-PI;   }   else if(speedX<0 && speedY==0){   rotRad=-PI/2;   }   else if(speedX==0 && speedY<0){   rotRad=0;   }   //if it's already on the spot (which is impossible) or there's some sort of caluclation error.   else {   rotRad=0;   println("error: cannot determine quadrant");   }     //set start position as the first incremental position   tempX=startX;   tempY=startY;     //get a scale value so the flies don't look the same size   flyScale=random(.7,1.3);     //generate a value for the tint   flyTintVal=round(random(0,160));   }     void move(){   //figure out if the fly's position needs to move, depending on where it is and how close it is to its end position     if(speedX>=0){   //1. if the temporary position went beyond the end position,   //2. if the remaining position is less than its usual pace   //3. if the speed for that axis is 0   //make the next temporary position as the end position for that axis   if(tempX>endX || endX-tempX<speedX || speedX==0){   tempX=endX;   }   else {   tempX=tempX+speedX;   }   }   else {   //this is for if the fly is moving in a negative direction, but basically the same idea as the procedure above.   if(tempX<endX || endX-tempX>speedX){   tempX=endX;   }   else {   tempX=tempX+speedX;   }   }     if(speedY>=0){   //see X above for explanation   if(tempY>endY || endY-tempY<speedY || speedY==0){   tempY=endY;   }   else {   tempY=tempY+speedY;   }   }   else {   if(tempY<endY || endY-tempY>speedY){   tempY=endY;   }   else {   tempY=tempY+speedY;   }   }   //complicated math went into this.   // newTempX=tempHype*cos(asin(tempY/tempHype)-rotRad);   // newTempY=tempHype*sin(acos(tempX/tempHype)-rotRad);   }     void display(){   //old example using only circles   //fill(0,128,255);   //stroke(0);   //ellipse(tempX,tempY,10,10);     //old way to rotate   //rotate the image, place the image in the new position, then rotate the canvas back to allow for the next object to use it.   // rotate(rotRad);   // image(flyImg,newTempX,newTempY);   // rotate(-rotRad);     //new way to rotate   //using translate and rotate together allow you to move individual objects. but make sure to move it back, either with pushMatrix()/popMatrix or using negative values   pushMatrix();   pushStyle();   translate(tempX,tempY);   rotate(rotRad);   tint(flyTintVal);   image(flyImg,0,0,flyDefaultWidth*flyScale,flyDefaultHeight*flyScale);   popStyle();   popMatrix();   }  } // end of Fly class