collision with many particles and walls
@author
float e = 0.5;
float k = 0.3;
ArrayList<Particle> particles;
void setup(){
size(500, 500);
noStroke();
frameRate(30);
particles = new ArrayList<Particle>();
while(particles.size() < 50){
float radius = random(5, 30);
PVector loc = new PVector(random(radius, width - radius), random(radius, height - radius));
boolean isOverlapping = false;
for(Particle p: particles){
if(PVector.dist(loc, p.loc) <= radius + p.radius){
isOverlapping = true;
break;
}
}
if(!isOverlapping){
float velSize = 5.0;
float velAng = random(TWO_PI);
PVector vel = new PVector(velSize * cos(velAng), velSize * sin(velAng));
particles.add(new Particle(loc, vel, radius));
}
}
}
void draw(){
background(#007FB1);
for(Particle p: particles){
p.render();
p.move();
}
for(Particle p: particles){
p.reflectFromWalls();
}
for(Particle p1: particles){
for(Particle p2: particles){
if(p1 == p2){continue;}
p1.addImpulse(p2);
}
}
for(Particle p: particles){
p.updateVel();
}
}
class Particle{
PVector loc, vel, nvel;
float radius, mass;
color c;
Particle(PVector loc, PVector vel, float radius){
this.loc = loc;
this.vel = vel;
this.nvel = new PVector(vel.x, vel.y);
this.radius = radius;
this.mass = 1.0;
if(radius < 15){
c = color(#AEC1E3);
} else {
c = color(#95DFD6);
}
}
void move(){
loc.add(vel);
}
void render(){
fill(c);
ellipse(loc.x, loc.y, radius * 2, radius * 2);
}
void reflectFromWalls(){
if(loc.x < radius){
reflectFromWall(new PVector(1, 0));
}
if(loc.x > width - radius){
reflectFromWall(new PVector(-1, 0));
}
if(loc.y < radius){
reflectFromWall(new PVector(0, 1));
}
if(loc.y > height - radius){
reflectFromWall(new PVector(0, -1));
}
}
void reflectFromWall(PVector n){
PVector vn = PVector.mult(n, PVector.dot(vel, n));
PVector vt = PVector.sub(vel, vn);
vel = PVector.add(PVector.mult(vn, -1), vt);
nvel = new PVector(vel.x, vel.y);
loc.add(vel);
}
void addImpulse(Particle p){
float d = PVector.dist(loc, p.loc);
if(d <= radius + p.radius){
PVector pDiff = PVector.sub(p.loc, loc);
PVector n = PVector.div(pDiff, pDiff.mag());
PVector vDiff = PVector.sub(p.vel, vel);
float spring = -k * (radius + p.radius - d);
float j = (1 + e) * (mass * p.mass / (mass + p.mass)) * PVector.dot(vDiff, n);
PVector impulse = PVector.mult(n, j + spring);
nvel.add(impulse);
}
}
void updateVel(){
vel = nvel;
nvel = new PVector(vel.x, vel.y);
}
}