Ball[] myBalls; // declaring a global variable to hold an array of Ball objects int ballNumber = 100; //set up array to contain maximum number of balls int alive = 25; //how many balls are actually on the screen int timer=0; //used for when mouse is pressed to cycle through ball colors int mouseBallx = -100; //used to position a ball created by the mouse (values are set to mousex,y) int mouseBally = -100; int selectedColor=1; //one of three colors can be the evolution color. 1=red, 2=green,3=blue int bTrans = 5; //for overaly transparency float compLevel = .1; // change the level at which it decides to let creatures breed or eat each other depending on no of creatures int counter = 1; int cornerCounter = 1; boolean clicked = false;//was the mouse just clicked? void setup() { background(255); size(600,500); framerate(25); myBalls = new Ball[ballNumber]; // create the array to hold ball objects int i=0; //create 25 balls and position them for (int y=0;y<10;y++){ for (int x=0;x<10;x++){ myBalls[i] = new Ball(i); // populating the array // with new Ball objects myBalls[i].x = x*80; myBalls[i].y = y*80; if (i > 0) myBalls[i].dx = myBalls[i-1].dx*-1; if (i > 1) myBalls[i].dy = myBalls[i-2].dy*-1; myBalls[i].redColor = int(random(255)); myBalls[i].greenColor = int(random(255)); myBalls[i].blueColor = int(random(255)); myBalls[i].breathing = false; i++; } } for (int r=0;r<25;r++) myBalls[r].breathing=true; } void loop() { bTrans = 12; fill(255,bTrans); //semi transparent background overlay to create fading effect noStroke(); rect(0,0,599,499); //step the actual physics code 2 times. for (int t = 0; t < 2; t++) { for (int z = 0; z < ballNumber; z++)myBalls[z].dirty = 0; //prevent collision because one just recorded? 0=no for (int z = 0; z < ballNumber; z++)myBalls[z].run(); //check to see if a collision for (int z = 0; z < ballNumber; z++)myBalls[z].run2(); //change direction of ball if collision for (int z = 0; z < ballNumber; z++)myBalls[z].run3(); //bounce off edges of screen } for (int z=0; z< ballNumber; z++)myBalls[z].colorCorrect(); //if a ball has collided then change its color and shape based 'evolution' for (int z = 0; z < ballNumber; z++)myBalls[z].drawShape(); //draw the ball image checkmouse(); } void checkmouse() { if (mousePressed==true) { timer=timer+1; noStroke(); noFill(); if (timer <= 10) { stroke(255,0,0); fill(255,0,0); //background(255,0,0); selectedColor=1; } else if (timer > 10 && timer <= 20 ) { stroke(0,255,0); fill(0,255,0); // background(0,255,0); selectedColor=2; }else if (timer > 20 && timer <= 30) { stroke(0,0,255); fill(0,0,255); // background(0,0,255); selectedColor=3; }else if (timer > 25) { timer = 0; } mouseBallx=mouseX; mouseBally=mouseY; ellipseMode(CENTER_RADIUS); //int s=(y/3)+5; int s=10; ellipse(mouseBallx,mouseBally,s,s); } } void mouseReleased() { for (int z = 0; z < ballNumber; z++) { if (selectedColor==1) { myBalls[z].domColor=myBalls[z].redColor; myBalls[z].color2=myBalls[z].greenColor; myBalls[z].color3=myBalls[z].blueColor; } else if (selectedColor==2) { myBalls[z].domColor=myBalls[z].greenColor; myBalls[z].color2=myBalls[z].redColor; myBalls[z].color3=myBalls[z].blueColor; } else if (selectedColor==3) { myBalls[z].domColor=myBalls[z].blueColor; myBalls[z].color2=myBalls[z].redColor; myBalls[z].color3=myBalls[z].greenColor; } if (myBalls[z].domColor+myBalls[z].color2+myBalls[z].color3 != 0) { myBalls[z].colorPower = float(myBalls[z].domColor/(myBalls[z].domColor+myBalls[z].color2+myBalls[z].color3)); } else { myBalls[z].colorPower = .0000001; } } for (int z = 0; z < ballNumber; z++) { if (myBalls[z].breathing==false) { myBalls[z] = new Ball(z); myBalls[z].x = mouseBallx; myBalls[z].y = mouseBally; myBalls[z].ball_size=20; myBalls[z].user=10; mouseBally= -100; mouseBallx = -100; myBalls[z].breathing=true; alive=alive+1; break; } } //println ("clicked"); } //class class Ball { float x; float y; float dx = 1; float dy = 1; int ball_size=int(random(10)+3); int me; int collision = 0; int dirty = 0; int dirtyCounter = 0; //used when something is dirty for too long int opacity = 100; int redColor = 100; int greenColor= 100; int blueColor=100; int userSelected = 0; float domColor; float color2; float color3; float colorPower = .33; boolean breathing=true; int other = 0; int last_other = 0; int user=0; Ball(int ME) { me = ME; } //collision detect void run() { if (breathing == true) { for (int q = 0; q < alive; q++) { if (q != me) { if (myBalls[q].breathing==true) { //get the distance between the two balls using pythagorean float xdiff = x - myBalls[q].x; float ydiff = y - myBalls[q].y; float dist = sqrt((xdiff*xdiff)+(ydiff*ydiff)); //swap trajectories to emulate bouncing. //if the distance is small enough. if(dist<=ball_size+myBalls[q].ball_size+1){ if (dirty != 0) { dirtyCounter+=1; //println("called"); } if (dirtyCounter >= 3) { dirtyCounter = 0; myBalls[q].dirty =0; dirty = 0; } if(dirty==0 && myBalls[q].dirty==0){ float tmpx = myBalls[q].dx; float tmpy = myBalls[q].dy; myBalls[q].dx = dx; myBalls[q].dy = dy; dx = tmpx; dy = tmpy; if (dx == myBalls[q].dx && dy == myBalls[q].dy) { dx *= -1; dy *= -1; } //set them to dirty = 1 myBalls[q].dirty = 1; //change to 1 to allow only 1 hit dirty=1; //change to 1 to allow only 1 hit other = q; } break; } } } } //detect collision for mouseBall if (mouseBallx != - 100) { //get the distance between the two balls using pythagorean float xdiff = x - mouseBallx; float ydiff = y - mouseBally; float dist = sqrt((xdiff*xdiff)+(ydiff*ydiff)); if(dist<=ball_size + 10 +1){ dx *= -1; dy *= -1; } } } } void run2(){ x += dx; y += dy; } void run3(){ //here is the new bounce off edges, without the lingering at the edges. if(y > height - (ball_size/2)) { y = height - (ball_size/2); dy *= -1; } if(y < (ball_size/2)) { y = (ball_size/2); dy *= -1; } if(x < (ball_size/2) ) { x = (ball_size/2) ; dx *= -1; } if(x > width - (ball_size/2) ) { x = width - (ball_size/2) ; dx *= -1; } } void colorCorrect() { if (breathing == true) { if (last_other !=other) { if (myBalls[other].breathing==true) { float compatibility = colorPower - myBalls[other].colorPower; float compatibilityN = 0.0; if (compatibility < 0.0) { compatibilityN = compatibility * -1.0; } else { compatibilityN = compatibility; } //println ("N " + compatibilityN); if (alive < 33) { compLevel = .1; } else if (alive < 66) { compLevel = .075; } else if (alive < 83) { compLevel = .04; } else if (alive < 93) { compLevel = .01; } else { compLevel = 0.0; } //println(alive); if ((compatibilityN) < compLevel) { marriage(); } else if (compatibility < 0.0) { //if (myBalls[other].domColor < 251) myBalls[other].domColor += 5; //if (myBalls[other].color2 > 4) myBalls[other].color2 -= 5; //if (myBalls[other].color3 > 4) myBalls[other].color3 -= 5; if (myBalls[other].ball_size<125) myBalls[other].ball_size+=2; // if (domColor > 4) domColor -= 5; //if (color2 < 251) color2 += 5; //if (color3 < 251) color3 += 5; //if (ball_size > 2) breathing = false; alive-=1; breathing = false; } else if (compatibility > 0.0) { // if (domColor < 251) domColor += 5; //if (color2 > 4) color2 -= 5; //if (color3 > 4) color3 -= 5; if (ball_size<125) ball_size+=2; //if (myBalls[other].domColor > 4) myBalls[other].domColor -= 5; //if (myBalls[other].color2 < 251) myBalls[other].color2 +=5; //if (myBalls[other].color3 < 251) myBalls[other].color3 += 5; alive-=1; myBalls[other].breathing = false; } } last_other = other; } } } void drawShape() { if (breathing==true) { ellipseMode(CENTER_RADIUS); stroke(redColor,greenColor,blueColor); if (user==10) { fill(200,200,200); } else { fill(255); } ellipse(x, y, ball_size, ball_size); } } void marriage() { if (ball_size > 1) { ball_size -= 1; for (int z=0; z < ballNumber; z++) { if (myBalls[z].breathing == false) { birth(z); break; } } } } void birth (int baby) { myBalls[baby] = new Ball(baby); myBalls[baby].redColor = (redColor-10) + int(random(20)); myBalls[baby].greenColor = (greenColor-10) + int(random(20)); myBalls[baby].blueColor = (blueColor-10) + int(random(20)); if (myBalls[baby].redColor > 255) myBalls[baby].redColor = 255; if (myBalls[baby].greenColor > 255) myBalls[baby].greenColor = 255; if (myBalls[baby].blueColor > 255) myBalls[baby].blueColor = 255; if (myBalls[baby].redColor < 0) myBalls[baby].redColor = 0; if (myBalls[baby].greenColor < 0) myBalls[baby].greenColor = 0; if (myBalls[baby].blueColor < 0) myBalls[baby].blueColor = 0; //establish its fitness-also redone everytime the mouse is used... if (selectedColor==1) { myBalls[baby].domColor=myBalls[baby].redColor; myBalls[baby].color2=myBalls[baby].greenColor; myBalls[baby].color3=myBalls[baby].blueColor; } else if (selectedColor==2) { myBalls[baby].domColor=myBalls[baby].greenColor; myBalls[baby].color2=myBalls[baby].redColor; myBalls[baby].color3=myBalls[baby].blueColor; } else if (selectedColor==3) { myBalls[baby].domColor=myBalls[baby].blueColor; myBalls[baby].color2=myBalls[baby].redColor; myBalls[baby].color3=myBalls[baby].greenColor; } if (myBalls[baby].domColor+myBalls[baby].color2+myBalls[baby].color3 != 0) { myBalls[baby].colorPower = float(myBalls[baby].domColor/(myBalls[baby].domColor+myBalls[baby].color2+myBalls[baby].color3)); } else { myBalls[baby].colorPower = .0000001; } //decide where it will be 'born' if (cornerCounter ==1) { myBalls[baby].x = 0; myBalls[baby].y = 0; cornerCounter +=1; } else if (cornerCounter ==2) { myBalls[baby].x = 0; myBalls[baby].y = 500; cornerCounter+=1; } else if (cornerCounter ==3) { myBalls[baby].x = 600; myBalls[baby].y = 0; cornerCounter+=1; } else if (cornerCounter ==4) { myBalls[baby].x = 600; myBalls[baby].y = 500; cornerCounter+=1; } else if (cornerCounter ==5) { myBalls[baby].x = 600; myBalls[baby].y = 250; cornerCounter+=1; } else if (cornerCounter ==6) { myBalls[baby].x = 0; myBalls[baby].y = 250; cornerCounter+=1; } else if (cornerCounter ==7) { myBalls[baby].x = 300; myBalls[baby].y = 0; cornerCounter+=1; } else if (cornerCounter ==8) { myBalls[baby].x = 300; myBalls[baby].y = 500; cornerCounter+=1; } else if (cornerCounter ==9) { myBalls[baby].x = 400; myBalls[baby].y = 500; cornerCounter+=1; } else if (cornerCounter ==10) { myBalls[baby].x = 200; myBalls[baby].y = 0; cornerCounter=1; } alive+=1; //println("birth " + baby); } }