class Curver{ Vec3D position; Vec3D prevPosition; Vec3D heading; Vec3D prevHeading; float step; float age; float turnPerStep; float newTurnPerStep; boolean overEdge; boolean shrinking; float ageStep; boolean inactive; boolean polarity; Curver(){ position = new Vec3D(random((float)width),random((float)height),0f); prevPosition=new Vec3D(position); heading = new Vec3D(random(-1f,1f),random(-1f,1f),0f); heading.normalize(); prevHeading = new Vec3D(heading); age=1.0f; step=1.0f; newTurnPerStep=turnPerStep=random(0.001f,0.005f)*(random(100f)<50f?-1f:1f); overEdge=false; ageStep=0.005f; inactive=false; shrinking=false; polarity=(random(100f)<50f)?true:false; } Curver(Vec3D position, Vec3D heading){ this.position = new Vec3D(position); prevPosition=new Vec3D(position); this.heading = new Vec3D(heading); heading.normalize(); prevHeading = new Vec3D(heading); age=1.0f; step=1.0f; newTurnPerStep=turnPerStep=random(0.001f,0.005f)*(random(100f)<50f?-1f:1f); overEdge=false; ageStep=0.005f; inactive=false; shrinking=false; polarity=(random(100f)<50f)?true:false; } void reset(){ heading = new Vec3D(random(-1f,1f),random(-1f,1f),0f); position = new Vec3D(random((float)width),random((float)height),0f); heading.normalize(); prevPosition.set(position); prevHeading.set(heading); overEdge=false; age=1.0f; step=1.0f; //ageStep*=0.9f; newTurnPerStep=turnPerStep=random(0.001f,0.005f)*(random(100f)<50f?-1f:1f); inactive=false; shrinking=false; polarity=(random(100f)<50f)?true:false; } void update(int[][] Grid){ prevPosition.set(position); prevHeading.set(heading); overEdge=false; position.addSelf(heading.scale(step)); if(position.x<2){ position.x+=width-4; overEdge=true; } if(position.x>=width-2){ position.x-=width-4; overEdge=true; } if(position.y<2){ position.y+=height-4; overEdge=true; } if(position.y>=height-2){ position.y-=height-4; overEdge=true; } if (shrinking){ age-=4*ageStep; if (age<1.0f) inactive=true; } else{ age+=ageStep; } Vec3D newHeading = new Vec3D(heading.x*cos(turnPerStep)-heading.y*sin(turnPerStep),heading.y*cos(turnPerStep)+heading.x*sin(turnPerStep),0f); heading.set(newHeading); if(shrinking){ turnPerStep=0.99f*turnPerStep+newTurnPerStep; } else{ if(random(100f)<1f) newTurnPerStep=random(0.001f,0.005f)*(random(100f)<50f?-1f:1f); turnPerStep=0.99f*turnPerStep+0.01f*newTurnPerStep; } if(overEdge){ inactive=true; } if(grid[(int)(position.x+step*heading.x)][(int)(position.y+step*heading.y)]>0){ shrinking=true; } grid[(int)position.x][(int)position.y]++; } void draw(color[][] colorGrid){ noStroke(); fill(0); ellipse(position.x,position.y,age,age); if(!shrinking){ stroke(colorGrid[(int)position.x][(int)position.y]); float randomL = (polarity)?random(age*10.0f):-random(age*10.0f); line(position.x,position.y,position.x+randomL*heading.y,position.y-randomL*heading.x); if(age>1.5f){ randomL = (polarity)?random(age*10.0f-15.0f):-random(age*10.0f-15.0f); ellipse(position.x-randomL*heading.y,position.y+randomL*heading.x,0.5f*age,0.5f*age); } } else{ if(age>2.0f){ fill(255,random(120f,256f),random(120f,256f)); ellipse(position.x-random(-20f,20f)*heading.y,position.y+random(-20f,20f)*heading.x,4f*age,4f*age); } } //ellipse(position.x+randomL*heading.y,position.y-randomL*heading.x,0.5f*age,0.5f*age); } }