class Wormtype { int nr; float x,y; // position float xmov, ymov; // movement vector float cD; // crawlDirection float cF; // crawlFrequency float age; // controls crawl frequency float agility; // controls followers; float agA, agB; // ease of agility float spd; // basic speed float s; // actual speed float colr1=120,colg1=64,colb1=0; float colr2=40,colg2=70,colb2=160; color myColor; int type; // type of worm int nrOfFollowers=5; boolean severalPaths; followDot[] follower=new followDot[nrOfFollowers+1]; Wormtype(int n) { type=n%3;//n%3; // 0..1..2 nr=n; init(); } void init() { age=random(2,70); //max 80 x=random(width); y=random(height); // position cD=random(-PI,PI); // crawl direction cF=0.2+2.0 / ((age)/8.0); // crawl frequency spd=3/sqrt(age); // basic speed if (type<3) { myColor=color(colr1+type*40+random(10),colg1+type*35+random(10),colb1+type*12+random(5)); } s=0.0; xmov=spd*cos(cD); ymov=spd*sin(cD); agility=agA=1+12*(age/80.0); agB=agA+1; for (int i=1;i<=nrOfFollowers;i++) { follower[i]=new followDot(x,y,agility); } } void update() { // GETTING OLDER: age+=0.01; if (age>=80) { age=1; } // worm reincarnates! cF=0.2+2.0 / ((age)/8.0); // crawl frequency spd=3/sqrt(age); // basic speed agility=agA=1+12*(age/80.0); agB=agA+1; // WORM SPEED: s=spd*(sin(cF*TWO_PI*millis()/1000.0)+1)*0.5; // FIND NUMBER OF FRIENDS AND ENEMIES WITHIN A RADIUS OF 30 float sx=warpedX(x), sy=warpedY(y); float nrOfFriends=0.0, nrOfEnemies=0.0; float frx=0.0, fry=0.0, enx=0.0, eny=0.0; for (int w=1;w<=nrOfWorms;w++) { if (w!=nr) { if (dist(sx,sy,warpedX(worm[w].x),warpedY(worm[w].y))<30) { if (worm[w].type==type) { nrOfFriends+=1.0; frx+=(warpedX(worm[w].x)-sx); fry+=(warpedY(worm[w].y)-sy); } else { nrOfEnemies+=1.0; enx-=(warpedX(worm[w].x)-sx); fry+=(warpedY(worm[w].y)-sy); } } } } // BEHAVIOUR: I really want to go to my friends if (nrOfFriends>0) { frx/=nrOfFriends; fry/=nrOfFriends; xmov+=0.0001*frx; ymov+=0.0001*fry; } // BEHAVIOUR: I don't mind too much to be with my enemies, but I still dislike them.. if (nrOfEnemies>0) { enx/=nrOfEnemies; eny/=nrOfEnemies; xmov-=0.000001*enx; ymov-=0.000001*eny; } // BEHAVIOUR: I like walking on a path of my own color: // which dot around me is closest to my color? int closedotX=-10, closedotY=-10; float colorDiff=1.0,lastColorDiff=1.0; severalPaths=false; for (int xo=-1;xo<=1;xo++) { for (int yo=-1;yo<=1;yo++) { // check color for every pixel around x/y pixel; color getColor=get(int(warpedX(x+xo)),int(warpedY(y+yo))); if (getColor!=backGroundColor) { colorDiff=getColorDifference(myColor,getColor); if (colorDiff this is a path! closedotX=xo; closedotY=yo; lastColorDiff=colorDiff; severalPaths=false; } if (colorDiff==lastColorDiff) { severalPaths=true; } // if there are several paths .... } } } if (closedotX!=-10&&closedotY!=-10&&!severalPaths) { /// ... there is no path xmov+=0.05*closedotX; ymov+=0.05*closedotY; } cD=atan2(ymov,xmov); // BEHAVIOUR: I feel free to go where i want float tRot=cD+HALF_PI*age/50.0*random(-1.0,1.0); cD=(agA*cD+tRot)/agB; // crawl direction // new movement vector: xmov=s*cos(cD); ymov=s*sin(cD); x+=xmov; y+=ymov; stroke(myColor); pointScreen(x,y,true,myColor); for (int i=1;i<=nrOfFollowers;i++) { if (i==1) { follower[i].update(x,y,agility); } else { follower[i].update(follower[i-1].x,follower[i-1].y,agility); } } } // function for getting difference between colors: 0=no difference 1=maximum difference float getColorDifference(color a, color b) { float dif=abs(red(a)-red(b))/(3.0*255.0); dif+=abs(green(a)-green(b))/(3.0*255.0); dif+=abs(blue(a)-blue(b))/(3.0*255.0); return dif; } }