xxxxxxxxxx
ArrayList<Leader> leaders = new ArrayList<Leader>();
ArrayList<Follower> followers = new ArrayList<Follower>();
PVector[] field;
int spacing = 20, k=0, orbSize = 2, numLeaders = 4, numFollowers = 8; //more leaders gives a more organic look when followers change leaders
float vecScl = 3000; //the size of the coloration giving the liquid effect
Follower ff = new Follower(200,200);
void setup() {
size(70,200);
background(200);
field = new PVector[width*height*2];
for(int x = 0; x<numLeaders; x++){
leaders.add( new Leader( floor(random(width)) , height ) );
}
leaders.get(0).vel= new PVector(0,-0.5); //just to make it start with one going straight up
for(int x = 0; x<numFollowers; x++){
followers.add( new Follower( floor(random(width)) , height ) );
followers.get(x).findLeader();
}
nextField();
//info for the viewer:
println("access code by clicking the button at the top : <\/>");
println("This simulation runs slowly in the browser because it's doing alot of calculations.");
println("Change the number of leaders, followers, and the size of the rectangle to customize.");
println("More followers & leaders or a bigger rectangle will make it slower.");
}
void draw() {
background(255);
if(frameCount%500==0){ nextField(); } //create a new field every now and then
for(Leader b : leaders){
b.applyField();
b.addDelay();
b.move();
b.edges(b.maxY); //stagger the bottom edge for leaders to prevent clumping on the bottom edge
//b.show(); //cannot see this if doing the pixel manipulation, keep off for better performance
}
for(Follower f: followers){
if(f.timeFollowing > 1000){
if(random(1)<0.3){
f.findLeader();
}else{
f.timeFollowing = 800;
}
}
if(f.following!=null){
f.followLeader();
}
f.applyField();
f.move();
f.edges(height);
//f.show(); //cannot see this if doing the pixel manipulation, keep off for better performance
}
showLava();
//showField();
//============border around canvas
stroke(0);
noFill();
strokeWeight(2);
rect(0,0,width, height);
//=======================================
}
/******************************
* Render the lava pixel-by-pixel
******************************/
void showLava(){
loadPixels();
for(int x=1; x<width; x+=2){
for(int y=1; y<height; y+=2){
int index = x + y * width;
pixels[index]= color(sum);
}
}
fill(255, 255, 0);
for(int x=0; x<width; x+=2){
for(int y=0; y<height; y+=2){
int index = x + y * width;
float d, sum = 0;
for(Leader l : leaders){
d = dist(x, y, l.pos.x, l.pos.y);
sum += l.blobRadius / d;
}
for(Follower f : followers){
d = dist(x, y, f.pos.x, f.pos.y);
sum += f.blobRadius / d;
}
if(sum>255) { sum = 255; }
if(sum<250) { sum/=2; }
pixels[index]= color(sum);
}
}
updatePixels();
}
/******************************
* Show the field vectors that move the lava around
******************************/
void showField(){
stroke(0);
for(int j = 0; j<=height; j+=spacing){
for(int i = 0; i<=width; i+=spacing){ //start in the middle of each square
int location = i + j * width;
PVector p = field[location];
pushMatrix();
translate(i, j);
rotate(p.heading());
line(0,0,p.mag()*vecScl,0);
ellipse(p.mag()*vecScl, 0, 2,2);
popMatrix();
}
}
}
/******************************
* Create a new field to prevent orbs from falling into a pattern
******************************/
void nextField(){
k+=random(3);
for(int j = 0; j<=height; j+=spacing){
float pMag = map(j, 0, height, spacing/vecScl, -spacing/vecScl);
for(int i = 0; i<=width; i+=spacing){ //start in the middle of each square
int location = i + j * width;
float angle = map(noise(i,j,k), 0, 1, PI, 0);
PVector p = PVector.fromAngle(angle);
p = PVector.mult(p, pMag);
field[location] = p;
}
}
}
//