xxxxxxxxxx
121
let movers = [];
let liquid;
function setup() {
// text must be before create graphics
let text = createP("Click mouse to reset");
createCanvas(560,390);
reset();
// create liquid object
// coefficient of drag(0.1) is low otherwise object would come to faily quick
liquid = new Liquid(0, height/2, width, height/2, 0.1);
// call methods of each element to set location and id
text.position(10,5);
}
function draw() {
background(220);
liquid.display(); // draw liquid
for (let i = 0; i < movers.length; i++) {
if (liquid.contains(movers[i])) { // check if Mover is inside liquid
let dragForce = liquid.calculateDrag(movers[i]); // calculate drag force
movers[i].applyForce(dragForce); // Mover apply drag force
}
let gravity = createVector(0, 0.1 * movers[i].mass); // gravity is scaled by mass
movers[i].applyForce(gravity); // Mover apply gravity
// update and display
movers[i].update();
movers[i].display();
movers[i].checkEdges();
}
}
// reset all the Mover objects randomly
function reset() {
for (let i = 0; i < 9; i++) {
movers[i] = new Mover(random(0.5, 3), 40 + i * 70, 0);
}
}
function mousePressed() {
reset();
}
class Liquid {
// liquid object will be a rectangle and has location, width, height, and coefficient of drag
constructor(x, y, w, h, c) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.c = c;
}
// if Mover is inside the rectangle defined by the Liquid class
contains(m) {
let l = m.location;
return l.x > this.x && l.x < this.x + this.w &&
l.y > this.y && l.y < this.y + this.h;
}
// calculate drag force
calculateDrag(m) {
// magnitude = coefficient * speed * speed
let speed = m.velocity.mag();
let dragMagnitude = this.c * speed * speed;
// force direction is inverse of velocity = -1 * velocity
let dragForce = m.velocity.copy();
dragForce.mult(-1);
// scale according to magnitude
dragForce.normalize();
dragForce.mult(dragMagnitude); // finalize the force, magnitude and direction together
return dragForce;
}
display() {
noStroke();
fill(100);
rect(this.x, this.y, this.w, this.h);
}
}
class Mover {
constructor(m, x, y) {
this.mass = m;
this.location = createVector(x, y);
this.velocity = createVector(0, 0);
this.acceleration = createVector(0, 0);
}
// Newton's 2nd law: F = M * A, so A = F / M
applyForce(force) {
let f = p5.Vector.div(force, this.mass);
this.acceleration.add(f);
}
update() {
this.velocity.add(this.acceleration); // velocity changes according to acceleration
this.location.add(this.velocity); // location changes by velocity
this.acceleration.mult(0); // clearing acceleration for each frame
}
display() {
stroke(0);
strokeWeight(2);
fill(63,63,147);
ellipse(this.location.x, this.location.y, this.mass*16, this.mass*16);
}
// bounce off bottom of window
checkEdges() {
if (this.location.y > height) {
this.velocity.y *= -0.9; // a little dampening when hitting the bottom
this.location.y = height;
}
}
}