xxxxxxxxxx
202
var ropes = [];
function setup() {
createCanvas(600, 600);
ropes.push(new Rope(100, 100, 200));
}
function draw() {
background(220);
for (let r of ropes) {
r.update();
}
}
///// CLASS /////
let C_GRAVITY = 1;
let DISTANCE_BTW_BALLS = 30;
class Spring {
constructor(a, b, restLength, stiffness) {
this.bobA = a;
this.bobB = b;
this.len = restLength;
this.k = stiffness; // spring constant
}
update() {
let vector = p5.Vector.sub(this.bobB.pos, this.bobA.pos);
let distance = vector.mag();
let stretch = distance - this.len;
let strength = -1 * stretch * this.k; // hooke's law
// force to bobB
let force = vector.copy();
force.normalize();
force.mult(strength);
this.bobB.applyForce(force);
// force to bobB
let force1 = vector.copy();
force1.normalize();
force1.mult(strength * -1);
this.bobA.applyForce(force1);
//text(strength.toFixed(2), this.bobB.pos.x + 50, this.bobB.pos.y);
}
display() {
push();
stroke(255);
strokeWeight(10);
line(this.bobA.pos.x, this.bobA.pos.y, this.bobB.pos.x, this.bobB.pos.y);
pop();
}
}
class Ball {
constructor(x, y, rad) {
this.pos = createVector(x, y);
this.vel = createVector(0, 0);
this.acc = createVector(0, 0);
this.rad = rad;
this.mass = rad * 0.5; // MASS!
//
this.damping = 0.8;
}
update() {
this.vel.add(this.acc);
this.pos.add(this.vel);
this.acc.mult(0);
// let's apply damping here
this.vel.mult(this.damping); // -5%;
}
applyForce(f) {
if (this.mass > 0) {
let force = p5.Vector.div(f, this.mass);
this.acc.add(force);
}
}
attractedTo(others) {
for (let i = 0; i < others.length; i++) {
let other = others[i];
if (this != other) {
let distance = this.pos.dist(other.pos);
let magnitude =
(C_GRAVITY * this.mass * other.mass) / (distance * distance);
let force = p5.Vector.sub(other.pos, this.pos);
force.normalize();
force.mult(magnitude);
this.applyForce(force);
}
}
}
repelledFrom(others) {
// this method is duplicated from attractedTo()
// then, the force vector is flipped.
for (let i = 0; i < others.length; i++) {
let other = others[i];
if (this != other) {
let distance = this.pos.dist(other.pos);
if (distance < this.rad + DISTANCE_BTW_BALLS) {
let magnitude =
(C_GRAVITY * this.mass * other.mass) / (distance * distance);
let force = p5.Vector.sub(other.pos, this.pos);
force.normalize();
force.mult(-1); // ***
force.mult(magnitude);
this.applyForce(force);
}
}
}
}
reappear() {
if (this.pos.x < 0) {
this.pos.x = width;
} else if (this.pos.x > width) {
this.pos.x = 0;
}
if (this.pos.y < 0) {
this.pos.y = height;
} else if (this.pos.y > height) {
this.pos.y = 0;
}
}
bounce() {
// x
if (this.pos.x < 0) {
this.pos.x = 0;
this.vel.x = -this.vel.x;
} else if (this.pos.x > width) {
this.pos.x = width;
this.vel.x = -this.vel.x;
}
// y
if (this.pos.y < 0) {
this.pos.y = 0;
this.vel.y = -this.vel.y;
} else if (this.pos.y > height) {
this.pos.y = height;
this.vel.y = -this.vel.y;
}
}
drag() {
if (mouseIsPressed) {
let distance = dist(this.pos.x, this.pos.y, mouseX, mouseY);
if (distance < this.rad) {
// in
this.pos.x = mouseX;
this.pos.y = mouseY;
}
}
}
display() {
push();
translate(this.pos.x, this.pos.y);
noStroke();
fill(255, 200);
//circle(0, 0, this.rad * 2);
pop();
}
}
class Rope {
constructor(x, y, len) {
this.balls = [];
this.springs = [];
let t;
for (let i = 0; i <= len; i += 10) {
let b = new Ball(x, y + i, 6);
this.balls.push(b);
if (t != null) {
this.springs.push(new Spring(t, b, 5, 2));
}
t = b;
}
t = null;
}
update() {
for (let s of this.springs) {
s.update();
s.display();
}
for (let i = 0; i < this.balls.length; i++) {
let b = this.balls[i];
if (i == 0) {
b.pos.x = lerp(b.pos.x, mouseX, 0.5);
b.pos.y = lerp(b.pos.y, mouseY, 0.5);
}
b.drag();
b.bounce();
b.applyForce(createVector(0, 2));
b.update();
b.display();
}
}
}