Source
let system;
let wind;
let waterLine = 400;
function setup() {
createCanvas(600, 600);
system = new System();
let ball = new Ball(100, 100, 25, "red");
system.addObject(ball);
ball = new Ball(100, 100, 10, "blue");
system.addObject(ball);
for (let i = 0; i < 20; i++){
ball = new Ball(random(10, width-10), random(10, waterLine-10), 10, "blue");
system.addObject(ball);
}
const gravity = {
base: createVector(0,1),
applyTo(obj){
obj.applyForce(p5.Vector.mult(this.base, obj.mass));
}
}
system.addForce(gravity);
wind = {
base: createVector(0,0),
applyTo(obj){
obj.applyForce(this.base);
}
}
system.addForce(wind);
const drag = {
dragCoefficient: .2,
applyTo(obj){
// don't do anything if it isn't in the water
if (obj.radius+obj.position.y > waterLine){
const v = obj.velocity.copy().normalize();
v.mult(-this.dragCoefficient * obj.velocity.magSq());
obj.applyForce(v);
}
}
}
system.addForce(drag);
}
function draw() {
background(255);
if (mouseIsPressed){
wind.base.x = width/2 - mouseX;
wind.base.y = height/2 - mouseY;
wind.base.normalize();
wind.base.mult(30);
console.log(wind.base)
}else{
wind.base.mult(0);
}
fill(100,100,255,100);
rect(0, waterLine, width, height-waterLine);
system.update();
system.draw();
noFill();
stroke("black");
rect(0,0,width, height);
}
class System{
objects = [];
forces = [];
addObject(obj){
this.objects.push(obj);
}
addForce(force){
this.forces.push(force);
}
update(){
for (let force of this.forces){
for (let obj of this.objects){
force.applyTo(obj);
}
}
for (let obj of this.objects){
obj.update();
}
}
draw(){
for (let obj of this.objects){
obj.draw();
}
}
}
class Ball {
constructor(x, y, radius, color) {
this.radius = radius;
this.mass = radius;
this.color = color;
this.position = createVector(x, y);
this.velocity = createVector(1,0);
this.force = createVector(0,0);
}
applyForce(force){
this.force.add(force);
}
update(){
const acceleration = p5.Vector.div(this.force, this.mass);
this.force.x = 0;
this.force.y = 0;
this.velocity.add(acceleration);
this.position.add(this.velocity);
if ((this.position.x - this.radius< 0 && this.velocity.x < 0)
|| (this.position.x + this.radius >= width && this.velocity.x > 0)){
this.velocity.x *= -.9;
}
if ((this.position.y - this.radius < 0 && this.velocity.y < 0)
|| (this.position.y + this.radius >= height && this.velocity.y > 0)){
this.velocity.y *= -.9;
}
this.position.x = min(width - this.radius, max(this.radius, this.position.x));
this.position.y = min(height - this.radius, max(this.radius, this.position.y));
}
draw(){
fill(this.color);
circle(this.position.x, this.position.y, this.radius*2);
}
}