<script type="application/processing">
// amoebaAbstract_01_formatik
// Copyright 2003 Marius Watz
// http://www.evolutionzone.com/
//
// Variation on abstract computational animation for the exhibition
// "Abstraction Now", K�nstlerhaus Vienna, 29.08-28.09 2003.
//
// You are allowed to play with this code as much as you like, but
// you may not publish pieces based directly on it. The Vec2D class
// can be used freely in any context.
//
int num,cnt,px,py,fadeInterval;
Particle[] particles;
boolean initialised=false,doClear=false;
float lastRelease=-1,scMod,fadeAmount;
void setup() {
size(500,600);
background(255);
smooth();
rectMode(CENTER_DIAMETER);
ellipseMode(CENTER_DIAMETER);
cnt=0;
num=150;
particles=new Particle[num];
for(int i=0; i<num; i++) particles[i]=new Particle();
reinit();
px=-1;
py=-1;
}
void draw() {
if(doClear) {
background(255);
doClear=false;
}
noStroke();
if(frameCount%fadeInterval==0) {
fill(255,255,255, fadeAmount);
rect(width/2,height/2, width,height);
}
updateAuto();
for(int i=0; i<num; i++)
if(particles[i].age>0) particles[i].update();
}
void reinit() {
doClear=true;
scMod=random(1,1.4);
fadeInterval=(int)random(220,300);
fadeAmount=random(30,60);
// println("fadeInterval "+fadeInterval+" scMod "+nf(scMod,0,3)+
// " fadeAmount "+nf(fadeAmount,0,3));
for(int i=0; i<num; i++) particles[i].age=-1;
initAuto();
}
void mousePressed() {
reinit();
}
AutoMover auto[];
int autoN;
void initAuto() {
autoN=(int)random(3,6);
// println("initAuto "+autoN);
auto=new AutoMover[autoN];
for(int i=0; i<autoN; i++) auto[i]=new AutoMover();
}
void updateAuto() {
for(int i=0; i<autoN; i++) auto[i].update();
}
class AutoMover {
Vec2D pos,posOld;
float dir,dirD,speed,sc,dirCnt;
int type,age,ageGoal,interval;
AutoMover() {
reinit();
}
void reinit() {
ageGoal=(int)random(150,350);
if(random(100)>95) ageGoal*=1.25;
age=-(int)random(50,150);
pos=new Vec2D(random(width-100)+50,random(height-100)+50);
dir=(int)random(36)*10;
type=0;
if(random(100)>60) type=1;
interval=(int)random(2,5);
if(type==1) {
interval=1;
dir=degrees(atan2(-(pos.y-height/2),pos.x-width/2));
}
dirD=random(1,2);
if(random(100)<50) dirD=-dirD;
speed=random(3,6);
sc=random(0.5,1);
if(random(100)>90) sc=random(1.2,1.6);
dirCnt=random(20,35);
if(type==0) {
if(random(100)>95) sc=random(1.5,2.25);
else sc=random(0.8,1.2);
}
sc*=scMod;
speed*=sc;
}
void update() {
age++;
if(age<0) return;
else if(age>ageGoal) reinit();
else {
if(type==1) {
pos.add(
cos(radians(dir))*speed,sin(radians(dir))*speed);
dir+=dirD;
dirD+=random(-0.2,0.2);
dirCnt--;
if(dirCnt<0) {
dirD=random(1,5);
if(random(100)<50) dirD=-dirD;
dirCnt=random(20,35);
}
}
if(age%interval==0) newParticle();
if(pos.x<-50 || pos.x>width+50 ||
pos.y<-50 || pos.y>height+50) reinit();
}
}
void newParticle() {
int partNum,i;
if(type==0) dir=int(random(36))*10;
i=0;
while(i<num) {
if(particles[i].age<1) {
float offs=random(30,90);
if(random(100)>50) offs=-offs;
particles[i].init(dir+offs,pos.x,pos.y,sc);
break;
}
i++;
}
px=mouseX;
py=mouseY;
}
}
class Particle {
Vec2D v,vD;
float dir,dirMod,speed,sc;
int col,age,stateCnt;
int type;
Particle() {
v=new Vec2D(0,0);
vD=new Vec2D(0,0);
age=0;
}
void init(float _dir,float mx,float my,float _sc) {
dir=_dir;
sc=_sc;
float prob=random(100);
if(prob<80) age=15+int(random(30));
else if(prob<99) age=45+int(random(50));
else age=100+int(random(100));
if(random(100)<80) speed=random(2)+0.5;
else speed=random(2)+2;
if(random(100)<80) dirMod=20;
else dirMod=60;
v.set(mx,my);
initMove();
dir=_dir;
stateCnt=10;
if(random(100)>50) col=0;
else col=1;
type=(int)random(30000)%2;
}
void initMove() {
if(random(100)>50) dirMod=-dirMod;
dir+=dirMod;
vD.set(speed,0);
vD.rotate(radians(dir+90));
stateCnt=10+int(random(5));
if(random(100)>90) stateCnt+=30;
}
void update() {
age--;
if(age>=30) {
vD.rotate(radians(1));
vD.mult(1.01f);
}
v.add(vD);
if(col==0) fill(255-age,0,100,150);
else fill(100,200-(age/2),255-age,150);
if(type==1) {
if(col==0) fill(255-age,100,0,150);
else fill(255,200-(age/2),0,150);
}
pushMatrix();
scale(sc);
translate(v.x,v.y);
rotate(radians(dir));
rect(0,0,1,16);
popMatrix();
if(age==0) {
if(random(100)>50) fill(200,0,0,200);
else fill(00,200,255,200);
float size=2+random(4);
if(random(100)>95) size+=5;
size*=sc;
ellipse(v.x*sc,v.y*sc,size,size);
}
if(v.x<0 || v.x>width || v.y<0 || v.y>height) age=0;
if(age<30) {
stateCnt--;
if(stateCnt==0) {
initMove();
}
}
}
}
// General vector class for 2D vectors
class Vec2D {
float x,y;
Vec2D(float _x,float _y) {
x=_x;
y=_y;
}
Vec2D(Vec2D v) {
x=v.x;
y=v.y;
}
void set(float _x,float _y) {
x=_x;
y=_y;
}
void set(Vec2D v) {
x=v.x;
y=v.y;
}
void add(float _x,float _y) {
x+=_x;
y+=_y;
}
void add(Vec2D v) {
x+=v.x;
y+=v.y;
}
void sub(float _x,float _y) {
x-=_x;
y-=_y;
}
void sub(Vec2D v) {
x-=v.x;
y-=v.y;
}
void mult(float m) {
x*=m;
y*=m;
}
void div(float m) {
x/=m;
y/=m;
}
float length() {
return sqrt(x*x+y*y);
}
float angle() {
return atan2(y,x);
}
void normalise() {
float l=length();
if(l!=0) {
x/=l;
y/=l;
}
}
Vec2D tangent() {
return new Vec2D(-y,x);
}
void rotate(float val) {
// Due to float not being precise enough, double is used for the calculations
double cosval=Math.cos(val);
double sinval=Math.sin(val);
double tmpx=x*cosval - y*sinval;
double tmpy=x*sinval + y*cosval;
x=(float)tmpx;
y=(float)tmpy;
}
}
</script>
<canvas width="500px" height="600px" id="processing"></canvas>