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){ 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-tempXspeedX){ tempX=endX; } else { tempX=tempX+speedX; } } if(speedY>=0){ //see X above for explanation if(tempY>endY || endY-tempYspeedY){ 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