/* built with Studio Sketchpad:
* https://sketchpad.cc
*
* observe the evolution of this sketch:
* https://fgcs.sketchpad.cc/sp/pad/view/ro.RItsaTB-n9i/rev.1951
*
* authors:
* Lachlan Dalaigh Wilger
* Markus Roberts
* license (unless otherwise specified):
* creative commons attribution-share alike 3.0 license.
* https://creativecommons.org/licenses/by-sa/3.0/
*/
// Pressing Control-R will render this sketch.
int len = 20;
float seg_length = 3;
float [] x;
float [] y;
float [] dx;
float [] dy;
float [] m;
int ball = len-1;
float seconds_per_frame;
void setup() {
size(300, 300);
smooth();
frameRate(30);
seconds_per_frame = 1.0/30.0;
strokeWeight(2);
x = new float[len];
y = new float[len];
for (i=0; i<len; i++) y[i] = i*seg_length*3;
dx = new float[len];
dy = new float[len];
m = new float[len];
for (i=0; i<len; i++) m[i] = 0.1;
m[0] = 10000;
m[ball] = 10;
}
float dist_(int p1, float x2, float y2) {
return sqrt(sq(x[p1]-x2)+sq(y[p1]-y2));
}
float dist(int p1, int p2) {
return dist_(p1,x[p2],y[p2]);
}
void draw() {
// Yay, physics!
for (step=0;step<50;step++) {
for (i=1;i<len;i++) {
x[i] = x[i]+dx[i]*seconds_per_frame;
y[i] = y[i]+dy[i]*seconds_per_frame;
float friction = (1-0.0001/m[i]);
dx[i] = friction*(dx[i]+0.0001*random(-5,5));
dy[i] = friction*(dy[i]+0.002); // gravity
}
for (i=1;i<len;i++) {
float d = dist(i,i-1);
if (d > seg_length) {
float stretch = (d-seg_length)/seg_length;
float total_m = m[i]+m[i-1];
float ax = seconds_per_frame*10*((x[i]-x[i-1])/d)*stretch/total_m;
float ay = seconds_per_frame*10*((y[i]-y[i-1])/d)*stretch/total_m;
dx[i] = dx[i ]-m[i-1]*ax;
dy[i] = dy[i ]-m[i-1]*ay;
dx[i-1] = dx[i-1]+m[i ]*ax;
dy[i-1] = dy[i-1]+m[i ]*ay;
}
}
}
// Now draw the results...
background(255);
stroke(0);
middle = width/2;
for (i=1;i<len;i++) line(middle+x[i-1], y[i-1], middle+x[i], y[i]);
fill(0);
ellipse(middle+x[ball],y[ball],40,40);
}
float prior_mouse_X,prior_mouse_Y;
void mouseMoved() {
if (dist_(ball,mouseX,mouseY) <= 40) {
dx[ball] = dx[ball] + (mouseX-prior_mouse_X);
dy[ball] = dy[ball] + (mouseX-prior_mouse_Y);
}
prior_mouse_X = mouseX;
prior_mouse_Y = mouseY;
}
void mousePressed() {
float delta_x = (mouseX-width/2)-x[ball];
float delta_y = mouseY -y[ball];
for (int i=1;i<len;i++) {
x[i] = x[i]+(delta_x*sq(i))/sq(len);
y[i] = y[i]+(delta_y*sq(i))/sq(len);
}
}