javascriptDemo / simulation.js
Francis89074's picture
Create simulation.js
b0455ad verified
let particles = [];
const numParticles = 25;
let cylinderRadius = 200;
let cylinderHeight = 400;
let sphereRadius = 300;
let rotationAngle = 0;
let zoom = 1;
let zoomDirection = 1;
function setup() {
createCanvas(800, 800, WEBGL);
colorMode(HSB, 360, 100, 100);
for (let i = 0; i < numParticles; i++) {
particles.push(new Particle(
random(-cylinderRadius, cylinderRadius),
random(-cylinderHeight/2, cylinderHeight/2),
random(-cylinderRadius, cylinderRadius),
i * (360/numParticles)
));
}
}
function draw() {
background(0);
scale(zoom);
zoom += 0.002 * zoomDirection;
if (zoom > 1.5) zoomDirection = -1;
if (zoom < 0.8) zoomDirection = 1;
rotateY(rotationAngle);
rotationAngle += 0.005;
push();
noFill();
stroke(200, 50, 50, 50);
sphere(sphereRadius);
pop();
push();
noFill();
stroke(100, 50, 50, 50);
cylinder(cylinderRadius, cylinderHeight);
pop();
for (let particle of particles) {
particle.update();
particle.checkCollisions();
particle.display();
}
}
class Particle {
constructor(x, y, z, hue) {
this.pos = createVector(x, y, z);
this.vel = p5.Vector.random3D().mult(random(2, 5));
this.radius = 8;
this.hue = hue;
this.trail = [];
this.maxTrailLength = 20;
}
update() {
this.pos.add(this.vel);
this.trail.push(this.pos.copy());
if (this.trail.length > this.maxTrailLength) {
this.trail.splice(0, 1);
}
}
checkCollisions() {
let radialDist = sqrt(this.pos.x * this.pos.x + this.pos.z * this.pos.z);
if (radialDist + this.radius > cylinderRadius) {
let normal = createVector(this.pos.x, 0, this.pos.z).normalize();
let dotProduct = this.vel.dot(normal);
this.vel.sub(normal.mult(2 * dotProduct));
this.pos.set(
this.pos.x * (cylinderRadius - this.radius) / radialDist,
this.pos.y,
this.pos.z * (cylinderRadius - this.radius) / radialDist
);
}
if (this.pos.y + this.radius > cylinderHeight/2) {
this.vel.y = -abs(this.vel.y);
this.pos.y = cylinderHeight/2 - this.radius;
}
if (this.pos.y - this.radius < -cylinderHeight/2) {
this.vel.y = abs(this.vel.y);
this.pos.y = -cylinderHeight/2 + this.radius;
}
let distFromCenter = this.pos.mag();
if (distFromCenter + this.radius > sphereRadius) {
let normal = this.pos.copy().normalize();
let dotProduct = this.vel.dot(normal);
this.vel.sub(normal.mult(2 * dotProduct));
this.pos.setMag(sphereRadius - this.radius);
}
}
display() {
push();
noFill();
strokeWeight(2);
beginShape();
for (let i = 0; i < this.trail.length; i++) {
let alpha = map(i, 0, this.trail.length, 0, 100);
stroke(this.hue, 80, 100, alpha);
vertex(this.trail[i].x, this.trail[i].y, this.trail[i].z);
}
endShape();
fill(this.hue, 80, 100);
noStroke();
translate(this.pos.x, this.pos.y, this.pos.z);
sphere(this.radius);
pop();
}
}