チュートリアル | (トピック一覧へ戻る) |
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; } }
次のコードではMyParticleクラスにインタラクト・メソッドを追加し、 アトラクタ―だけでなく、パーティクル・エージェント自身にもお互いを引っ張り合う引力を定義しています。
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; } }
以下のコードではアトラクタ―などの外部の力の場の影響は無しに、 エージェント自身の引力だけで軌跡に影響を及ぼします。 軌跡は出発点や出発速度、他のエージェントとの間隔などの初期条件で 大きく変わります。この例では上下一列に並んだ状態から上下方向へ向けて 出発します。
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; } }