//Amoeba generator //prototype for an artificial animator //by A.Steed 2005 CastMember [] actor; Vec2 [] motes; void setup(){ size(450,300); actor = new CastMember[int(random(2,6))]; motes = new Vec2[200]; for(int i = 0; i < motes.length; i++) motes[i] = new Vec2(random(width), random(height)); for(int i = 0; i < actor.length; i++) actor[i] = new CastMember(); ellipseMode(CENTER); smooth(); framerate(24); } void draw(){ background(151,201,151); for(int i = 0; i < actor.length; i++){ actor[i].draw(); actor[i].move(); } stroke(11,91,11); for(int i = 0; i < motes.length; i++){ motes[i] = drift(motes[i]); point(motes[i].x,motes[i].y); } } void mousePressed(){ actor = new CastMember[int(random(2,6))]; for(int i = 0; i < actor.length; i++) actor[i] = new CastMember(); } class CastMember{ Vec2 handle; //cast member's handle Vec2 [][] hull; //cast member's hull, 1st dimension: frame, 2nd dimension: co-ords Vec2 [] eye; //cast member's eyes float [] eyeSize; //size of eyes Vec2 tl,br; //bounding box corners int frame; //animation frame color col; //body color CastMember(){ frame = 0; float x = 0.0; float y = 0.0; handle = new Vec2(random(width), random(height)); int steps = int(random(20,37)); hull = new Vec2[int(random(2,6))][steps]; int d = int(random(4)); eye = new Vec2[int(random(1,3))]; eyeSize = new float[eye.length]; col = color(random(150,240),random(150,240),random(150,240),150); //generate hull for(int i = 0; i < hull.length; i++) for(int j = 0; j < hull[i].length; j++){ if(i == 0){ float theta = (TWO_PI / hull[i].length) * j; x = cos(theta) * random(30,45); y = sin(theta) * random(40,45); } else{ x = hull[0][j].x + random(-3,3); y = hull[0][j].y + random(-3,3); } hull[i][j] = new Vec2(x,y); } //generate bounding box tl = topLeft(hull[0]); br = bottomRight(hull[0]); //generate eyes x = 0.0; y = 0.0; while(true){ if(!isInside(x, y, hull[0])){ x = random(tl.x, br.x); y = random(tl.y, handle.y); } else { break; } } for(int i = 0; i < eye.length; i++){ eye[i] = new Vec2(x + random(10,20) * i, y); eyeSize[i] = random(10,15); } } void draw(){ stroke(0); fill(col); beginShape(POLYGON); curveVertex(handle.x + hull[frame][0].x, handle.y + hull[frame][0].y); for(int i = 0; i < hull[frame].length; i++){ curveVertex(handle.x + hull[frame][i].x, handle.y + hull[frame][i].y); } curveVertex(handle.x + hull[frame][0].x, handle.y + hull[frame][0].y); endShape(); for(int i = 0; i < eye.length; i++){ fill(255); ellipse(handle.x + eye[i].x, handle.y + eye[i].y, eyeSize[i], eyeSize[i]); fill(0); ellipse(handle.x + eye[i].x, handle.y + eye[i].y, 3, 3); } //for(int i = 0; i < hull.length; i++) //ellipse(hull[i].x, hull[i].y, 10, 10); //noFill(); //rect(tl.x, tl.y, br.x - tl.x, br.y - tl.y); frame = (frame+1)%hull.length; } void move(){ handle = drift(handle); } } Vec2 drift(Vec2 subject){ int go = int(random(4)); switch(go){ case 0: subject.x++; break; case 1: subject.y++; break; case 2: subject.x--; break; case 3: subject.y--; break; } return subject; } static class Vec2{ float x,y; Vec2(){ } Vec2(float x, float y){ this.x = x; this.y = y; } } //return the bounding box of a polygon Vec2 topLeft(Vec2 [] poly){ //calculate bounding box float xmin = width*2; float ymin = height*2; for(int i = 0; i < poly.length; i++){ if(poly[i].x < xmin) xmin = poly[i].x; if(poly[i].y < ymin) ymin = poly[i].y; } return new Vec2 (xmin, ymin); } Vec2 bottomRight(Vec2 [] poly){ //calculate bounding box float xmax = -(width*2); float ymax = -(height*2); for(int i = 0; i < poly.length; i++){ if(poly[i].x > xmax) xmax = poly[i].x; if(poly[i].y > ymax) ymax = poly[i].y; } return new Vec2 (xmax, ymax); } //is a given point inside a polygon of vectors? boolean isInside(float isX, float isY, Vec2 [] poly){ float theta = 0.0; for (int i = 1; i < poly.length+1; i++) theta += acuteAngle(isX, isY, poly[i-1].x, poly[i-1].y, poly[i%poly.length].x, poly[i%poly.length].y); if (abs(theta) < PI) return false; else return true; } float acuteAngle(float x0, float y0, float x1, float y1, float x2, float y2){ float theta0,theta1,dtheta; theta0 = atan2(y0-y1,x0-x1); theta1 = atan2(y0-y2,x0-x2); dtheta = theta1 - theta0; while (dtheta > PI) dtheta -= TWO_PI; while (dtheta < -PI) dtheta += TWO_PI; return dtheta; }