Duck mainDuck; ArrayList ducklings; ArrayList splashes; void setup(){ smooth(); size(500,500); mainDuck = new Duck(true); Duck followDuck = mainDuck; ducklings = new ArrayList(); for(int i =0; i < 4; i++){ Duck d = new Duck(false); d.setFollow(followDuck); ducklings.add(d); followDuck = d; } splashes = new ArrayList(); } void draw(){ // frameRate(2); background(50,50,150); ArrayList splashesToKill = new ArrayList(); for(Splash s: splashes){ if(!s.moveAndDraw()){ splashesToKill.add(s); } } //println(splashes.size()); splashes.removeAll(splashesToKill); for(Duck d : ducklings){ d.move(); d.draw(); } mainDuck.move(); mainDuck.draw(); } void mousePressed(){ mainDuck.kick(mouseX,mouseY,true); splashes.add(new Splash(mouseX,mouseY)); } class Duck{ float sz; float x,y,xs,ys; float bx, by; //the bx and by it is presenting to the world float a , ta, as; boolean isMain; Duck(boolean pd){ isMain = pd; if(isMain) sz = width / 13; else sz = width / 20; x = random(width/5,width*4/5); y = random(height/5,height*4/5); } void draw(){ drawDuck(x,y,sz,a); } Duck following; float dir; void setFollow(Duck d){ following = d; } void kick(float tx, float ty, boolean strong){ if(!strong){ //sometimes the little ducks ignore it if(!(random(1) < .1)){ return; } } splashes.add(new Splash(this)); dir = atan2(ty - y, tx - x) + random(-.4,.4); float mul = width/200; if(strong) mul = dist(x,y,tx,ty)/30; mul *= random(.8,1.5); xs = cos(dir) * mul; ys = sin(dir) *mul; ta = 0; a = -PI/4; if(xs < 0) { ta += PI; a = PI*5/4; } //a = ta; } void move(){ //bx and by are that target the duck is presenting if(following != null){ if(dist(following.bx,following.by,x,y) > width / 10){ kick(following.bx,following.by,false); } } x += xs; y += ys; bx = x + (cos(dir+PI) * (width/20)); by = y + (sin(dir+PI) * (width/20)); ys *= .95; xs *= .95; float d =dist(0,0,xs,ys); if(d > 0 && d < 0.1){ xs =0 ; ys = 0; splashes.add(new Splash(this)); } if(a < ta) as += .03; if(a > ta) as -= .03; as *= .9; if(abs(a - ta) < .1 && as < .02){ a = ta; as = 0; } a += as; } } void drawDuck(float x, float y, float sz, float a){ noStroke(); while(a < 0) a += 2 * PI; while(a > 2 * PI) a -= 2 * PI; int isLeftVal = -1; if(a / PI > .5 && a / PI < 1.5) { isLeftVal = 1; } pushMatrix(); translate(x,y); rotate(a); //LIPS pushMatrix(); fill(255,128,0); translate(sz/2 ,sz/5 * isLeftVal); ellipse(0,0,sz/3,sz/6); popMatrix(); fill(255,255,0); //BODY if(isLeftVal > 0) arc(0,0,sz,sz,PI,PI*2); else arc(0,0,sz,sz,0,PI); //HEAD ellipse(sz/4, isLeftVal * sz / 5, sz/2,sz/2); //EYE fill(0); ellipse(sz/4, isLeftVal * sz / 5, sz/8,sz/8); popMatrix(); } class Splash{ float x,y, st, sz; Splash(Duck d){ x = d.x; y = d.y + d.sz/2; st = 1; sz = 0; } Splash(float px, float py){ x = px; y = py; st = 1; sz = 0; } boolean moveAndDraw(){ if(st < 0) return false; st -= .005; sz += 1.5; strokeWeight(1); noFill(); stroke(50 + st * 60,50 + st * 50,150 + st*70); ellipse(x,y,sz,sz/4); return true; } }