Tutorials | (back to the list of tutorials) |
import processing.opengl.*; import igeo.*; void setup(){ size(480,360,IG.GL); IG.duration(360); int num=200; for(int i=0; i < num; i++){ IVec pos = IG.v(100,0,0).rot(2*PI*i/num); IVec vel = IG.v(-40,0,0).rot(2*PI*i/num); new MyParticle(pos, vel).fric(0.012).hsb(1.0/num*i,1,1); } for(int i=0; i < 8; i++){ new Attractor(IRand.pt(-120,-120,0,80,80,0)).clr(1.0,0,0); } } class Attractor extends IPointAgent{ final double threshold = 100; final double gravity = 300.0; final double minDist = 1.0; Attractor(IVec v){ super(v); } void interact(ArrayListagents){ for(int i=0; i < agents.size(); i++){ if(agents.get(i) instanceof MyParticle){ MyParticle agent = (MyParticle)agents.get(i); IVec dif = pos().dif(agent.pos()); double dist = dif.len(); if(dist < threshold){ if(dist < minDist){ dist = minDist; } double strength = gravity/dist; //the closer the larger IVec force = dif.len(strength); agent.push(force); } } } } } class MyParticle extends IParticle{ IVec prevPos; MyParticle(IVec p, IVec v){ super(p,v); } void update(){ IVec curPos = pos().cp(); if(prevPos!=null){ new ICurve(prevPos, curPos).clr(clr()); } prevPos = curPos; } }
The next code below adds interaction method in MyParticle to introduce gravity between particles themselves. The particles are taking forces not only towards the attractor agents but also other particle agents.
import processing.opengl.*; import igeo.*; void setup(){ size(480,360,IG.GL); IG.duration(450); int num=100; for(int i=0; i < num; i++){ if(IRand.pct(97)){ IVec pos = IG.v(100,0,0).rot(2*PI*i/num); IVec vel = IG.v(-20,0,0).rot(2*PI*i/num); new MyParticle(pos, vel).fric(0.001).hsb(1.0/num*i,1,1); } } for(int i=0; i < 3; i++){ new Attractor(IRand.pt(-120,-120,0,80,80,0)).clr(1.0,0,0); } } class Attractor extends IPointAgent{ final double threshold = 100; final double gravity = 300.0; final double minDist = 1.0; Attractor(IVec v){ super(v); } void interact(ArrayListagents){ for(int i=0; i < agents.size(); i++){ if(agents.get(i) instanceof MyParticle){ MyParticle agent = (MyParticle)agents.get(i); IVec dif = pos().dif(agent.pos()); double dist = dif.len(); if(dist < threshold){ if(dist < minDist){ dist = minDist; } double strength = gravity/dist; //the closer the larger IVec force = dif.len(strength); agent.push(force); } } } } } class MyParticle extends IParticle{ final double threshold = 30; final double gravity = 2.0; IVec prevPos; MyParticle(IVec p, IVec v){ super(p,v); } void interact(ArrayList < IDynamics > agents){ IVec center=null; int num=0; for(int i=0; i < agents.size(); i++){ if(agents.get(i) instanceof MyParticle){ MyParticle a = (MyParticle)agents.get(i); if(a != this){ if(a.pos().dist(pos()) < threshold){ if(center==null) center = a.pos().dup(); else{ center.add(a.pos()); } num++; } } } } if(num > 0){ center.div(num); IVec force = center.dif(pos()).mul(gravity); push(force); } } void update(){ IVec curPos = pos().cp(); if(prevPos!=null){ new ICurve(prevPos, curPos).clr(clr()); } prevPos = curPos; } }
The code below shows behavior of the particle agents with self gravity among the particles without any external attractors. It also changes the initial configuration of particle agents putting them on two lines.
import processing.opengl.*; import igeo.*; void setup(){ size(480,360,IG.GL); IG.duration(250); int num=100; for(int i=0; i < num; i++){ for(int j=0; j < 2; j++){ if(IRand.pct(70)){ IVec pos = IG.v(i, j*100, 0); IVec vel = IG.v(0, (30-j*55), 0); new MyParticle(pos, vel).fric(0.008).clr(IRand.clr()); } } } } class MyParticle extends IParticle{ final double threshold = 15; final double gravity = 25.0; IVec prevPos; MyParticle(IVec p, IVec v){ super(p,v); } void interact(ArrayList < IDynamics > agents){ IVec center=null; int num=0; for(int i=0; i < agents.size(); i++){ if(agents.get(i) instanceof MyParticle){ MyParticle a = (MyParticle)agents.get(i); if(a != this){ if(a.pos().dist(pos()) < threshold){ if(center==null) center = a.pos().dup(); else{ center.add(a.pos()); } num++; } } } } if(num > 0){ center.div(num); IVec force = center.dif(pos()).mul(gravity); push(force); } } void update(){ IVec curPos = pos().cp(); if(prevPos!=null){ new ICurve(prevPos, curPos).clr(clr()); } prevPos = curPos; } }