Tutorials | (back to the list of tutorials) |
Multi-Agent 2D Example 1![]()
![]()
![]()
![]()
import processing.opengl.*;
import igeo.*;
void setup(){
size(480,360,IG.GL);
IG.duration(150);
new LineAgent(IG.v(0,0,0), IG.v(1,0,0), PI/3, 20, 30, 100).clr(0.3);
new LineAgent(IG.v(100,0,0), IG.v(-1,0,0), PI/2, 20, 0, 100).clr(0.3);
new LineAgent(IG.v(-20,50,0), IG.v(0,-1,0), PI/2, 10, 0, 100).clr(0.3);
new LineAgent(IG.v(0,-100,0), IG.v(0,1,0), PI/2, 10, 10, 100).clr(0.3);
new LineAgent(IG.v(-40,0,0), IG.v(1,0,0), PI*0.4, 20, 30, 100).clr(0.3);
new LineAgent(IG.v(-100,40,0), IG.v(1,1,0), PI/2, 10, 10, 100).clr(0.3);
}
static class LineAgent extends IAgent{
static final double length = 2;
static final double clearance = 1.99; //less than lengthn
IVec pt1, pt2;
boolean isColliding=false;
double angle;
double pct1, pct2, pct3;
LineAgent(IVec pt, IVec dir, double ang,
double percent1,double percent2,double percent3){
pt1 = pt;
pt2 = pt.dup().add(dir.dup().len(length));
angle = ang;
pct1 = percent1;
pct2 = percent2;
pct3 = percent3;
}
void interact(ArrayList < IDynamics > agents){
if(time == 0){ //only in the first time
for(int i=0; i < agents.size() && !isColliding; i++){
if(agents.get(i) instanceof LineAgent){
LineAgent lineAgent = (LineAgent)agents.get(i);
if(lineAgent != this){ //agents include "this"
// checking clearance of end point
if(lineAgent.pt2.dist(pt2) < clearance){
isColliding=true;
}
}
}
}
}
}
void update(){
if(isColliding){ del(); }
else if(time == 0){ //if not colliding
new ICurve(pt1,pt2).clr(clr());
IVec dir = pt2.dif(pt1);
double r = red()+IRand.get(-0.03,0.03);
double g = green()+IRand.get(-0.03,0.03);
double b = blue()+IRand.get(-0.03,0.03);
if(IRand.pct(pct1)){ //bend
new LineAgent(pt2,dir.cp().rot(angle),angle,pct1,pct2,pct3).clr(r,g,b);
}
if(IRand.pct(pct2)){ //bend the other way
new LineAgent(pt2,dir.cp().rot(-angle),angle,pct1,pct2,pct3).clr(r,g,b);
}
if(IRand.pct(pct3)){ //straight
new LineAgent(pt2,dir.cp(),angle,pct1,pct2,pct3).clr(r,g,b);
}
}
}
}
Next, blocking agents are added to exclude some lines on some location. The class of blocking agents is BlockAgent. Comparing with the previous example of blocking agents, there is a difference in the location of the code which checks the location of agents and deletes. In the previous example, location checking is done in the interact method of LineBlockAgent but in the code below, LineAgent itself check the location of blocking agent inside its interact method. In the code below, branching angle and probability are randomly defined at setup method.
![]()
![]()
![]()
![]()
import processing.opengl.*;
import igeo.*;
void setup(){
size(480,360,IG.GL);
IG.duration(150);
for(int i=0; i < 15; i++){
new LineAgent(IRand.pt(300,200,0), IRand.dir(IG.zaxis),
IRand.get(PI*0.11,PI*0.3),IRand.get(90,100),
IRand.get(50,90),IRand.get(0,20)).clr(0);
}
new BlockAgent(IG.v(0,0,0), 20);
new BlockAgent(IG.v(-30,80,0), 30);
new BlockAgent(IG.v(50,50,0), 30);
new BlockAgent(IG.v(180,150,0), 50);
new BlockAgent(IG.v(0,-120,0), 80);
}
static class BlockAgent extends IAgent{
IVec pt;
double radius;
BlockAgent(IVec p, double r){
pt = p;
radius = r;
}
boolean isColliding(LineAgent agent){
if(agent.pt2.dist(pt) < radius){ return true; }
return false;
}
}
static class LineAgent extends IAgent{
static final double length = 2;
static final double clearance = 1.99; //less than length
IVec pt1, pt2;
boolean isColliding=false;
double angle;
double pct1, pct2, pct3;
LineAgent(IVec pt, IVec dir, double ang,
double percent1,double percent2,double percent3){
pt1 = pt;
pt2 = pt.dup().add(dir.dup().len(length));
angle = ang;
pct1 = percent1;
pct2 = percent2;
pct3 = percent3;
}
void interact(ArrayList < IDynamics > agents){
if(time == 0){ //only in the first time
for(int i=0; i < agents.size() && !isColliding; i++){
if(agents.get(i) instanceof LineAgent){
LineAgent lineAgent = (LineAgent)agents.get(i);
if(lineAgent != this){ //agents include "this"
// checking clearance of end point
if(lineAgent.pt2.dist(pt2) < clearance){
isColliding=true;
}
}
}
else if(agents.get(i) instanceof BlockAgent){
BlockAgent b = (BlockAgent)agents.get(i);
if(b.isColliding(this)){ isColliding=true; }
}
}
}
}
void update(){
if(isColliding){ del(); }
else if(time == 0){ //if not colliding
new ICurve(pt1,pt2).clr(clr());
IVec dir = pt2.dif(pt1);
double r = red()+IRand.get(-0.02,.035);
double g = green()+IRand.get(-0.02,.035);
double b = blue()+IRand.get(-0.02,.035);
if(IRand.pct(pct1)){ //bend
new LineAgent(pt2,dir.cp().rot(angle),angle,pct1,pct2,pct3).clr(r,g,b);
}
if(IRand.pct(pct2)){ //bend the other way
new LineAgent(pt2,dir.cp().rot(-angle),angle,pct1,pct2,pct3).clr(r,g,b);
}
if(IRand.pct(pct3)){ //straight
new LineAgent(pt2,dir.cp(),angle,pct1,pct2,pct3).clr(r,g,b);
}
}
}
}
The example below changes the branching angle inside the agent itself in the middle of the propagation process. In the update method, sometimes with a certain probability, the variable angle is increased or decreased stochastically. There is another stochastic feature added for the blocking agent. The line agent sometimes ignores the blocking agent and keep propagating inside the blocking area by if-condition in the interact method of LineAgent
![]()
![]()
![]()
![]()
import processing.opengl.*;
import igeo.*;
void setup(){
size(480,360,IG.GL);
IG.duration(150);
new LineAgent(IG.v(100,-50,0), IG.v(0,1,0), PI/2, 20,10,99).clr(0);
new LineAgent(IG.v(-50,150,0), IG.v(1,1,0), PI/2, 20,10,99).clr(0);
new BlockAgent(IG.v(0,0,0), 20);
new BlockAgent(IG.v(-30,80,0), 30);
new BlockAgent(IG.v(50,50,0), 30);
new BlockAgent(IG.v(180,150,0), 50);
new BlockAgent(IG.v(0,-120,0), 80);
}
static class BlockAgent extends IAgent{
IVec pt;
double radius;
BlockAgent(IVec p, double r){
pt = p;
radius = r;
}
boolean isColliding(LineAgent agent){
if(agent.pt2.dist(pt) < radius){ return true; }
return false;
}
}
static class LineAgent extends IAgent{
static final double length = 2;
static final double clearance = 1.99; //less than length
IVec pt1, pt2;
boolean isColliding=false;
double angle;
double pct1, pct2, pct3;
LineAgent(IVec pt, IVec dir, double ang,
double percent1,double percent2,double percent3){
pt1 = pt;
pt2 = pt.dup().add(dir.dup().len(length));
angle = ang;
pct1 = percent1;
pct2 = percent2;
pct3 = percent3;
}
void interact(ArrayList < IDynamics > agents){
if(time == 0){ //only in the first time
for(int i=0; i < agents.size() && !isColliding; i++){
if(agents.get(i) instanceof LineAgent){
LineAgent lineAgent = (LineAgent)agents.get(i);
if(lineAgent != this){ //agents include "this"
// checking clearance of end point
if(lineAgent.pt2.dist(pt2) < clearance){
isColliding=true;
}
}
}
else if(agents.get(i) instanceof BlockAgent){
BlockAgent b = (BlockAgent)agents.get(i);
if(b.isColliding(this)){
if(IRand.pct(80)){ //ignores block agent in 20%
isColliding=true;
}
}
}
}
}
}
void update(){
if(isColliding){ del(); }
else if(time == 0){ //if not colliding
new ICurve(pt1,pt2).clr(clr());
IVec dir = pt2.dif(pt1);
if(IRand.pct(2)){ //change angle occasionally
if(IRand.pct(50)){ angle+=PI/12; }
else{ angle -= PI/12; }
}
double r = red()+IRand.get(-0.03,0.03);
double g = green()+IRand.get(-0.03,0.03);
double b = blue()+IRand.get(-0.03,0.03);
if(IRand.pct(pct1)){ //bend
new LineAgent(pt2,dir.cp().rot(angle),angle,pct1,pct2,pct3).clr(r,g,b);
}
if(IRand.pct(pct2)){ //bend the other way
new LineAgent(pt2,dir.cp().rot(-angle),angle,pct1,pct2,pct3).clr(r,g,b);
}
if(IRand.pct(pct3)){ //straight
new LineAgent(pt2,dir.cp(),angle,pct1,pct2,pct3).clr(r,g,b);
}
}
}
}
HOME
FOR PROCESSING
DOWNLOAD
DOCUMENTS
TUTORIALS (Java /
Python)
GALLERY
SOURCE CODE(GitHub)
PRIVACY POLICY
ABOUT/CONTACT