int WIDTH = 400; int HEIGHT = 400; int BALLS = 50; int MINSIZE = 5; int MAXSIZE = 25; float GRAV = 0.3; int viewmode = 0; float distance(float x1, float y1, float x2, float y2) { return sqrt(sq(x1-x2) + sq(y1-y2)); } class Ball { float x, y, xvel, yvel, radius; int contact[] = new int[BALLS]; int cind = 0; Ball(float xIn, float yIn, float radiusIn) { x = xIn; y = yIn; radius = radiusIn; } void incontact(int obj) { contact[cind] = obj; cind++; } void update() { x += xvel; y += yvel; xvel *= 0.99; yvel *= 0.99; yvel += GRAV; if(y > HEIGHT-radius-1) { y = HEIGHT-radius; if(yvel > 2*GRAV) { yvel = -yvel*0.3; } else { yvel = 0; } xvel *= 0.95; } if(x > WIDTH-radius) { x = WIDTH-radius; if(xvel > 0) xvel = -xvel*0.9; } else if(x < radius) { x = radius; if(xvel < 0) { xvel = -xvel*0.9; } } } } class Pen { Ball b[] = new Ball[BALLS]; Pen() { createBalls(); } void createBalls() { b[0] = new Ball(0,0,15); for(int i = 1; i < BALLS; i++) { b[i] = new Ball(random(WIDTH), random(HEIGHT), random(MINSIZE, MAXSIZE)); } } void update() { float dir; float dist; for(int i = 1; i < BALLS; i++) { for(int u = 0; u < BALLS; u++) { if(i != u) { dist = distance(b[i].x, b[i].y, b[u].x, b[u].y) / (b[i].radius + b[u].radius); if(dist < 1) { // in contact b[i].incontact(u); b[i].xvel *= 0.95; b[i].yvel *= 0.95; dir = atan2((int)(b[u].y - b[i].y), (int)(b[u].x - b[i].x)); b[i].xvel += -15*(1-dist)*cos(dir); b[i].yvel += -15*(1-dist)*sin(dir); } } } } for(int i = 1; i < BALLS; i++) { b[i].update(); } b[0].x = mouseX; b[0].y = mouseY; } void jumble() { for(int i = 1; i < BALLS; i++) { b[i].xvel += random(-5,5); b[i].yvel += random(-10,1); } } void draw() { for(int i = 1; i < BALLS; i++) { ellipse(b[i].x, b[i].y, b[i].radius*2, b[i].radius*2); b[i].cind = 0; } /* if(viewmode == 3) { fill(#000000); noStroke(); for(int i = 1; i < BALLS; i++) { ellipse(b[i].x, b[i].y, b[i].radius*2+4, b[i].radius*2+4); } stroke(#000000); } if(viewmode != 1) { fill(#ffffff); for(int i = 1; i < BALLS; i++) { ellipse(b[i].x, b[i].y, b[i].radius*2, b[i].radius*2); } } for(int i = 1; i < BALLS; i++) { if(viewmode == 1 || viewmode == 2) { for(int u = 0; u < b[i].cind; u++) { line(b[i].x, b[i].y, b[b[i].contact[u]].x, b[b[i].contact[u]].y); } } b[i].cind = 0; } */ } } Pen p; void setup() { size(400, 400); background(#274081); ellipseMode(CENTER_DIAMETER); p = new Pen(); } void loop() { p.update(); p.draw(); } void mousePressed() { p.jumble(); }