Colourful ant-like particles
description
Particles created, move, interact, grow from encounters and disappear.click and drag to create new particles
Processing code:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
ArrayList<ant> ants; | |
long c = 0; | |
int maxpop = 1000; | |
void setup(){ | |
size(1250,870); | |
ants = new ArrayList<ant>(); | |
} | |
void draw(){ | |
background(0); | |
println(c); | |
autogen(); | |
for (int i = ants.size()-1; i >= 0; i--) { | |
ant a = ants.get(i); | |
a.update(); | |
a.display(); | |
if (a.isDead()) { | |
ants.remove(i); | |
} | |
} | |
} | |
void autogen(){ | |
if (ants.size ()< maxpop){ | |
ants.add(new ant(int(random(width)),int(random(height)), int(random(255)),int(random(255)),int(random(255)))); | |
} | |
} | |
void mousePressed(){ | |
ants.add(new ant(mouseX, mouseY, int(random(255)),int(random(255)),int(random(255)))); | |
} | |
void mouseDragged(){ | |
ants.add(new ant(mouseX, mouseY, int(random(255)),int(random(255)),int(random(255)))); | |
} | |
class ant { | |
long id; | |
float x=0,y=0; | |
int col1, col2, col3; | |
float vx=0, vy=0; | |
float ax=0,ay=0,thetha=0; | |
int lifespan, r; | |
ant(int x0, int y0, int colA, int colB, int colC){ | |
id=c; | |
lifespan =500; | |
x=x0; | |
y=y0; | |
ax=0; | |
ay=0; | |
col1 = colA; | |
col2 = colB; | |
col3 = colC; | |
r = int(random(0,2)); | |
c++; | |
} | |
void update(){ | |
thetha=random(2*PI); | |
ax=cos(thetha)/50; | |
ay=sin(thetha)/50; | |
vx+=ax; | |
vy+=ay; | |
//interaction between 2 ants | |
for (int i = ants.size()-1; i >= 0; i--) { | |
ant a = ants.get(i); | |
float dx = x-a.x; | |
float dy = y-a.y; | |
float d = sqrt(dx*dx + dy*dy); | |
//when 2 ants touch eachother, for the larger one, do the following : | |
if (id!=a.id && d-r-a.r<1 && r>a.r) { | |
//larger ant grows | |
r=min(r+1,100); | |
//smaller ant's shrinks and looses lifespan | |
a.r-=1; | |
a.lifespan-=3; | |
//smaller ant flees faster | |
a.vx*=1.1; | |
a.vy*=1.1; | |
//larger ant turns around | |
vx=-vx; | |
vy=-vy; | |
} | |
} | |
x+=vx; | |
y+=vy; | |
x=x%width; | |
y=y%height; | |
lifespan-=1; | |
} | |
void display(){ | |
stroke(col1, col2, col3, lifespan); | |
fill(col1, col2, col3, lifespan); | |
ellipse(int(x),int(y),r,r); | |
} | |
boolean isDead() { | |
if (lifespan < 0.0) { | |
return true; | |
} else { | |
return false; | |
} | |
} | |
} |
Automated vehicles reaching target and avoiding obstacles
description
Processing code:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
v2 added component parallel to v to steer force | |
*/ | |
ArrayList<Vehicle> cars; | |
ArrayList<Boulder> boulders; | |
PVector t; | |
color color_back = color(255,0,0); | |
color color_normal = color(175); | |
color color_emergency = color(255,255,0); | |
int fv = 180; | |
int dv =1; | |
int av = 5; | |
boolean dispsteer = true; | |
void setup(){ | |
background(0); | |
//size(900,700); | |
fullScreen(); | |
cars = new ArrayList<Vehicle>(); | |
boulders = new ArrayList<Boulder>(); | |
t = new PVector(width/2,height/2); | |
//create few boulders to start with | |
for (int i = 0; i<int(random(5,30)); i++){ | |
boulders.add(new Boulder(random(width),random(height))); | |
} | |
} | |
void draw(){ | |
//capture screen before erasing | |
loadPixels(); | |
//erase screen | |
background(0); | |
//target = new PVector(mouseX,mouseY); | |
//draw obstacles to be avoided by avoid function | |
//draw the frame around the screen | |
strokeWeight(5); | |
fill(0); | |
stroke(color_back); | |
rect(10,30,width-20,height-55); | |
//draw funnel obstacle around mouse location | |
//line(mouseX,mouseY-50,mouseX+300,mouseY-70); | |
//line(mouseX,mouseY+50,mouseX+300,mouseY+70); | |
strokeWeight(1); | |
//draw the boulders | |
for (int i = boulders.size()-1; i>=0;i--) { | |
Boulder b = boulders.get(i); | |
b.display(); | |
} | |
//update target | |
drawtarget(); | |
for (int i = cars.size()-1; i >= 0; i--) { | |
Vehicle v = cars.get(i); | |
//update target | |
//t.set(PVector.add(v.location,v.velocity.mult(2))); | |
// t = PVector.add(location,velocity.mult(2),new PVector(1,1)); | |
v.seek(t); | |
v.avoid(); | |
v.update(); | |
v.display(); | |
} | |
//write text | |
textSize(10); | |
fill(200); | |
text("press SPACE BAR to add car || drag mouse to move obstacles || press O to add new obstacle",10,10); | |
text("field of view (degrees) (press f to change ) :" + fv,10,22); | |
text("distance of view (press d to change ) :" + dv,400,22); | |
text("steering force to avoid (press a to change ) :" + av,800,22); | |
text("display steering vectors (press z) :" + dispsteer,10,height -5); | |
} | |
//draw obstacles when mouse is dragged | |
void mousePressed(){ | |
t.set(new PVector(mouseX,mouseY)); | |
drawtarget(); | |
} | |
void drawtarget(){ | |
stroke(0,255,255); | |
fill(0,255,255); | |
ellipse(t.x,t.y,40,40); | |
} | |
//handles keypressed events | |
void keyPressed() | |
{ | |
// creates new car when SPACE is pressed | |
if(key==32) { | |
cars.add(new Vehicle(random(20,width-20),random(40,height-20) )); | |
} | |
// creates new obstacle when "o" is pressed | |
if (key==111 ){ | |
boulders.add(new Boulder(random(width),random(height))); | |
} | |
// changes field of view when f is pressed | |
if (key==102 ){ | |
fv +=10; | |
fv= fv % 360; | |
for (int i = cars.size()-1; i >= 0; i--) { | |
Vehicle v = cars.get(i); | |
v.viewfield = fv; | |
} | |
} | |
// changes distance of view when d is pressed | |
if (key==100 ){ | |
dv +=1; | |
dv= dv % 20; | |
for (int i = cars.size()-1; i >= 0; i--) { | |
Vehicle v = cars.get(i); | |
v.viewdist = dv; | |
} | |
} | |
// changes force of steering when a is pressed | |
if (key==97 ){ | |
av +=1; | |
av= av % 15; | |
for (int i = cars.size()-1; i >= 0; i--) { | |
Vehicle v = cars.get(i); | |
v.avoidforce = av; | |
} | |
} | |
// toggles display steering vectors on / off | |
if (key==122 ){ | |
if(dispsteer == true) | |
{dispsteer = false; | |
} else { | |
dispsteer = true; | |
} | |
} | |
} | |
class Boulder { | |
float x,y,rx,ry; | |
Boulder(float a, float b) { | |
x=a; | |
y=b; | |
rx=random(5,70); | |
ry=random(10,90); | |
} | |
void display() { | |
fill(color_back); | |
stroke(color_back); | |
ellipse(x,y,rx,ry); | |
} | |
} | |
class Vehicle { | |
PVector location; | |
PVector velocity; | |
PVector acceleration; | |
//Additional variable for size | |
float r; | |
float maxforce; | |
float maxspeed; | |
int viewdist; | |
int viewfield; | |
int avoidforce; | |
int vision[]; | |
color vcolor; | |
Vehicle(float x, float y) { | |
acceleration = new PVector(0,0); | |
velocity = new PVector(1,0); | |
location = new PVector(x,y); | |
r = 5.0; | |
//Arbitrary values for maxspeed and force; try varying these! | |
maxspeed = 2; | |
maxforce = 0.1; | |
viewdist = dv; | |
viewfield = fv; | |
avoidforce = av; | |
vcolor = color_normal; | |
} | |
//Our standard āEuler integrationā motion model | |
void update() { | |
//removed update of velocity - moved to applyForce | |
location.add(velocity); | |
acceleration.mult(0); | |
} | |
//Newtonās second law; we could divide by mass if we wanted. | |
void applyForce(PVector force) { | |
acceleration.add(force); | |
//color c = color(255,1,1); | |
//drawSteer(acceleration,c); | |
//if(acceleration.mag()>0) {println(acceleration.mag());}; | |
velocity.add(acceleration); | |
color c = color(0,150,150); | |
drawSteer(velocity,c); | |
velocity.limit(maxspeed); | |
} | |
//Our seek steering force algorithm | |
void seek(PVector target) { | |
// fill(0); | |
// rect(target.x,target.y,5,5); | |
PVector desired = PVector.sub(target,location); | |
// measures distance from target | |
float d = desired.mag(); | |
// desired.normalize(); | |
//If we are closer than 100 pixels... | |
if (d < 100) { | |
//...set the magnitude according to how close we are. | |
float m = map(d,0,200,0,maxspeed); | |
desired.normalize(); | |
desired.mult(m); | |
} else { | |
//Otherwise, proceed at maximum speed. | |
desired.mult(maxspeed); | |
} | |
PVector steer = PVector.sub(desired,velocity); | |
steer.limit(maxforce); | |
//v2 add component to steer parallel to velocity | |
steer = PVector.add(steer, velocity.mult(1)); | |
// v2 in summary, use desired vecto to steer. substraction then addition of velocity useless | |
applyForce(desired.limit(maxforce*3)); | |
} | |
//look ahead in the direction of velocity : check color of the points at the next location(s) | |
//if color is the obscable's color to background, then steer in conseauence | |
void avoid(){ | |
float alpha,theta; | |
PVector scan = new PVector(0,0), futureloc = new PVector(0,0); | |
PVector obstacle = new PVector(0,0); | |
alpha = viewfield*PI/180/20; | |
for (int i=10;i>0;i--){ | |
for (int j=-10;j<11;j++){ | |
theta = velocity.heading(); | |
scan.set(i*viewdist*velocity.mag()*cos(theta+j*alpha),i*viewdist*velocity.mag()*sin(theta+j*alpha)); | |
futureloc = PVector.add(location,scan ); | |
// stroke(0,255,0); | |
//ellipse (futureloc.x,futureloc.y,1,1); | |
int cursor=int(abs(futureloc.x))+int(abs(futureloc.y))*width; | |
color p =pixels[min(cursor,width*height-1)]; | |
if (p == color_back || p == color_normal || p== color_emergency) | |
{ | |
//draw a circle at the location of interference | |
if(dispsteer==true) { | |
stroke(255); | |
ellipse (futureloc.x,futureloc.y,3,3); | |
} | |
//scale the obstacle detected higher as disctance decreases | |
scan.setMag(1*10/i); | |
obstacle = PVector.add(obstacle,scan); | |
} | |
} | |
} | |
//draw obstacle | |
color c = color(255,255,0); | |
drawSteer(obstacle,c); | |
//Emergency action | |
//if tracking right into obstacle, performs specific steering action | |
float a = PVector.angleBetween(velocity,obstacle); | |
if (abs(a)<PI/8 && obstacle.mag()>50) | |
{ | |
//sets vehicle color to specific | |
vcolor = color_emergency; | |
//rotates 90 degs the obstacle vector to steer in a specific direction | |
//or make a full stop | |
if (a != 0) { | |
obstacle.rotate(PI/4*a/abs(a)); | |
//obstacle.set(PVector.sub(velocity,acceleration)); | |
} else { | |
obstacle.rotate(PI/4); | |
//obstacle.set(PVector.sub(velocity,acceleration)); | |
} | |
//defines steering opposite to the obstacle | |
PVector steer = obstacle.mult(-1); | |
//draw the steering vector before scaling | |
//color c = color(255,1,1); | |
//drawSteer(steer,c); | |
//cap the steering force and apply | |
steer.limit(maxforce*avoidforce); | |
applyForce(steer); | |
} else | |
//Usual steering | |
{ | |
//sets vehicle color to normal | |
vcolor = color_normal; | |
//defines steering opposite to the obstacle | |
PVector steer = obstacle.mult(-1); | |
//draw the steering vector before scaling | |
//color c = color(0,255,0); | |
//drawSteer(steer,c); | |
//cap the steering force and apply | |
steer.limit(maxforce*avoidforce); | |
applyForce(steer); | |
} | |
} | |
void drawSteer(PVector s, color c) { | |
if(dispsteer==true) {PVector l= PVector.add(location,s); | |
stroke(c); | |
fill(c); | |
line(location.x,location.y, l.x,l.y); | |
ellipse(l.x,l.y,5,5); | |
} | |
} | |
void display() { | |
//Vehicle is a triangle pointing in the direction of velocity; since it is drawn pointing up, we rotate it an additional 90 degrees. | |
float theta = velocity.heading() + PI/2; | |
fill(vcolor); | |
stroke(0); | |
pushMatrix(); | |
translate(location.x,location.y); | |
rotate(theta); | |
beginShape(); | |
vertex(0,0); | |
vertex(-r, r); | |
vertex(-r, r*4); | |
vertex(r, r*4); | |
vertex(r,r); | |
endShape(CLOSE); | |
popMatrix(); | |
} | |
} | |
Coil spring
description
Processing code:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
ArrayList<coil> coils; | |
long c=20; | |
spring s; | |
void setup(){ | |
size(400,700); | |
coils = new ArrayList<coil>(); | |
s = new spring(); } | |
void draw(){ | |
background(0); | |
s.run(); | |
} | |
void keyPressed(){ | |
if (key == CODED) { | |
if (keyCode == UP) { | |
for (int i =0; i < coils.size()-1; i++){ | |
coil cc = coils.get(i); | |
cc.k+=1; | |
} | |
} else if (keyCode == DOWN) { | |
for (int i =0; i < coils.size()-1; i++){ | |
coil cc = coils.get(i); | |
cc.k-=1; | |
cc.k = max(1,cc.k); | |
} | |
} else if (keyCode == LEFT) { | |
for (int i =0; i < coils.size()-1; i++){ | |
coil cc = coils.get(i); | |
cc.dampening-=.02; | |
cc.dampening = max(0,cc.dampening); | |
} | |
} else if (keyCode == RIGHT) { | |
for (int i =0; i < coils.size()-1; i++){ | |
coil cc = coils.get(i); | |
cc.dampening+=.05; | |
cc.dampening = min(1,cc.dampening); | |
} | |
} | |
} | |
} | |
class spring{ | |
spring() { | |
for (int i=0;i<c;i++){ | |
coils.add(new coil(i)); | |
} | |
} | |
void run(){ | |
coil cc; | |
for (int i =0; i < coils.size()-1; i++){ | |
cc = coils.get(i); | |
cc.update(); | |
cc.display(); | |
} | |
} | |
} | |
class coil { | |
float x1,y1, k, m, dampening; | |
float a=0,v=0,d=0; | |
int id; | |
coil(int i){ | |
id=i; | |
x1=width/2; | |
y1=height/10; | |
a=0; | |
v=0; | |
dampening=0.1; | |
k=1; | |
m=500; | |
} | |
void update(){ | |
if (id>0){ | |
coil b = coils.get(id-1); | |
d= y1 - b.y1 +25; | |
a = -k*d/m - v *dampening; | |
v = (v + a); | |
y1 += v; | |
} else { | |
y1=mouseY; | |
} | |
} | |
void display(){ | |
fill(255); | |
stroke(255); | |
rect(int(x1),int(y1),50,5); | |
} | |
} |
Spring 2D
description
Processing code:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
ArrayList<coil> coils; | |
long c=10; | |
float kk=1, damp=0.1; | |
float gy=1, m=100; | |
spring s; | |
void setup(){ | |
size(1100,700); | |
coils = new ArrayList<coil>(); | |
s = new spring(); } | |
void draw(){ | |
background(0); | |
line(width/20,height,width/20,height-4*kk); | |
line(0,height/20,damp*width,height/20); | |
text("g:" + gy,10,10); | |
text("m:" + m, 70,10); | |
text("dampening:",5,height/21); | |
text("k:",width/21,height-5); | |
s.run(); | |
} | |
void keyPressed(){ | |
if (key == CODED) { | |
if (keyCode == UP) { | |
for (int i =0; i < coils.size()-1; i++){ | |
coil cc = coils.get(i); | |
cc.k+=1; | |
kk=cc.k; | |
} | |
} else if (keyCode == DOWN) { | |
for (int i =0; i < coils.size()-1; i++){ | |
coil cc = coils.get(i); | |
cc.k-=1; | |
cc.k = max(1,cc.k); | |
kk=cc.k; | |
} | |
} else if (keyCode == LEFT) { | |
for (int i =0; i < coils.size()-1; i++){ | |
coil cc = coils.get(i); | |
cc.dampening-=.05; | |
cc.dampening = max(0,cc.dampening); | |
damp=cc.dampening; | |
} | |
} else if (keyCode == RIGHT) { | |
for (int i =0; i < coils.size()-1; i++){ | |
coil cc = coils.get(i); | |
cc.dampening+=.05; | |
cc.dampening = min(1,cc.dampening); | |
damp=cc.dampening; | |
} | |
} | |
} else if (key == 'g' || key == 'G') | |
{gy+=1; | |
gy = gy % 9; | |
} | |
else if (key == 'm' || key == 'M') | |
{ | |
m+=100; | |
m=max(100,m % 2000); | |
} | |
} | |
class spring{ | |
spring() { | |
for (int i=0;i<c;i++){ | |
coils.add(new coil(i)); | |
} | |
} | |
void run(){ | |
coil cc; | |
for (int i =0; i < coils.size()-1; i++){ | |
cc = coils.get(i); | |
cc.update(); | |
cc.display(); | |
} | |
} | |
} | |
class coil { | |
float x1,y1, k, dampening; | |
float ax=0,ay=0,vx=0,vy=0,d=0,dx=0,dy=0,alpha=0; | |
int id; | |
coil(int i){ | |
id=i; | |
x1=width/2; | |
y1=height/2; | |
ax=0; | |
ay=0; | |
vx=0; | |
vy=0; | |
alpha=0; | |
dampening=damp; | |
k=kk; | |
} | |
void update(){ | |
if (id>0){ | |
coil b = coils.get(id-1); | |
dx = x1 - b.x1; | |
dy = y1 - b.y1; | |
d= sqrt(sq(dx) + sq(dy))-10; | |
if(dx<0){ | |
alpha=atan(dy/dx)+PI;} | |
else | |
{alpha=atan(dy/dx);} | |
ax = -k*d*cos(alpha)/m - vx *dampening; | |
//last term is gravity | |
ay = -k*d*sin(alpha)/m - vy *dampening+gy; | |
vx = vx + ax; | |
vy = vy + ay; | |
x1 +=vx; | |
y1 += vy; | |
} else { | |
x1=mouseX; | |
y1=mouseY; | |
} | |
} | |
void display(){ | |
fill(255); | |
stroke(255); | |
//rect(int(x1),int(y1),50,5); | |
if(id==0){ellipse(int(x1),int(y1),10,10);} | |
ellipse(int(x1),int(y1),max(10,d/10),max(10,d/10)); | |
} | |
} |
Comments
Post a Comment