Point p,b;
 
color col;
 
int h = 0;
 
Vector world = new Vector();
Vector con = new Vector();
 
void setup (){
 
size(550,500,P3D);
p = new Point(width/2,height/2);
b = new Point(width/2,height/2-1);
 
world.add(p);
world.add(b);
 
colorMode(HSB,100);
col = color(10,100,100);
con.add(new Constraint(p,b));
 
for (int i =0; i < 100; i++){
mouseClicked();
}
 
}
 
 
void draw(){
h++;
if (h>2000) h = 0;
col = color(h/20,100,100);
fill(0,0,0,2);
noStroke();
rect(0,0,width,height);
stroke(col);
Node node;
for (int i =0; i < world.size(); i++){
node = (Node)world.elementAt(i);
node.physics();
}
 
for (int i =0; i < con.size(); i++){
node = (Node)con.elementAt(i);
node.physics();
}
 
p.x -= (p.x-mouseX)/100.f;
p.y -= (p.y-mouseY)/100.f;
 
}
 
class Point extends Node{
 
float lx =0, ly =0;
float tly,tlx;
float x=0,y=0;
 
float ax = 0, ay =0.0;
 
public Point(float x, float y){
this.x = x;
this.y = y;
this.lx = x;
this.ly = y;
}
void physics(){
tly = y;
tlx = x;
x = 2*x - lx + ax;
y = 2*y - ly + ay;
ly = tly;
lx = tlx;
}
 
void render(){
pushMatrix();
translate(x,y);
ellipse(0,0,5,5);
popMatrix();
}
 
}
 
class Constraint extends Node{
 
Point a,b;
public Constraint(Point a, Point b){
this.a = a;
this.b = b;
}
public void physics(){
float dx = b.x-a.x;
float dy = b.y-a.y;
float d1 = sqrt(dx*dx + dy*dy);
float d2 = .5*(d1-20)/d1;
dx *= d2;
dy *= d2;
a.x += dx;
b.x -= dx;
a.y += dy;
b.y -= dy;
if (a.y > height){
}
if (b.y > height){
}
fill(col);
beginShape(QUADS);
vertex(a.x,a.y);
vertex(b.x,b.y);
vertex(b.lx,b.ly);
vertex(a.lx,a.ly);
endShape();
}
}
 
 
void mouseDragged(){
 
p.x += (p.x-mouseX)/1000.f;
p.y -= (p.y-mouseY)/1000.f;
 
}
 
void keyPressed(){
if (key == 'w') p.y -= 2;
if (key == 's') p.y += 2;
if (key == 'a') p.x -= 2;
if (key == 'd') p.x += 2;
 
}
 
void mouseClicked(){
Point temp = new Point(width/2,height/2);
 
con.add(new Constraint((Point)world.lastElement(),temp));
world.add(temp);
}
 
 
abstract class Node{
 
abstract public void physics();
 
}