Tutorials | (back to the list of tutorials) |
Multi-Agent 2D Example 4![]()
![]()
![]()
![]()
import igeo.*;
import processing.opengl.*;
void setup(){
size(480,360,IG.GL);
IRand.init(3);
IG.duration(700);
new LineAgent(IG.v(-0.1,0,0), IG.v(1,0,0)).clr(0);
new LineAgent(IG.v(500,-0.1,0), IG.v(0,1,0)).clr(0);
new LineAgent(IG.v(500+0.1,500,0), IG.v(-1,0,0)).clr(0);
new LineAgent(IG.v(0,500+0.1,0), IG.v(0,-1,0)).clr(0);
for(int i=0; i < 10; i++){
new LineAgent(IRand.pt(100,100,0,400,400,0), IRand.pt(-10,-10,0,10,10,0)).clr(IRand.clr(0.4,0.4,0.4));
}
}
static class LineAgent extends IAgent{
// constants
static final double length = 2;
static final double clearance = 1.99; //less than length
static final double angleThreshold = PI/20;
static final double threshold = 10;
IVec pt1, pt2;
boolean isColliding=false;
double angle=0;
double minDist=0;
double frontAngle=0;
LineAgent(IVec pt, IVec dir){
pt1 = pt;
pt2 = pt.cp(dir.cp().len(length));
}
void interact(ArrayList < IDynamics > agents){
if(time == 0){ //only in the first time
minDist = -1; //reset
for(int i=0; i < agents.size() && !isColliding; i++){
if(agents.get(i) instanceof LineAgent){
LineAgent agent = (LineAgent)agents.get(i);
if(agent != this){ //agents include "this"
// checking clearance of end point
double dist = agent.pt2.dist(pt2);
if(dist < clearance){ isColliding=true; }
else if(dist < threshold){ //not colliding but close
if(!pt1.eq(agent.pt2) && //not the parent
pt2.dif(pt1).angle(agent.pt2.dif(pt1)) < angleThreshold && //in front
(minDist < 0 || dist < minDist) ){ //closest one
minDist = dist;
frontAngle = pt2.dif(pt1).angle(agent.pt2.dif(agent.pt1),IG.zaxis);
}
}
}
}
}
}
}
void update(){
if(time == 0){
if(isColliding){ del(); }
else{ //if not colliding
new ICurve(pt1,pt2).clr(clr());
IVec dir = pt2.dif(pt1);
if(IRand.pct(1)){ //branching
double r = red()+IRand.get(-0.1,0.1);
double g = green()+IRand.get(-0.1,0.1);
double b = blue()+IRand.get(-0.1,0.1);
new LineAgent(pt2, dir.cp().rot(IRand.get(PI/3,2*PI/3))).clr(r,g,b);
}
if(frontAngle < 0){ frontAngle+=PI; } //going in only one direction
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);
new LineAgent(pt2, dir.rot(frontAngle)).clr(r,g,b);
}
}
}
}
The next code change the previous code to round the turning corner by bending the lines with a few segments. To enable bending through multiple generation of agents, the instance field of bendAngle and bendCount are added to LineAgent class.
![]()
![]()
![]()
![]()
import igeo.*;
import processing.opengl.*;
void setup(){
size(480,360,IG.GL);
IRand.init(2);
IG.duration(700);
new LineAgent(IG.v(-0.1,0,0),IG.v(1,0,0),0,0).clr(0);
new LineAgent(IG.v(500,-0.1,0),IG.v(0,1,0),0,0).clr(0);
new LineAgent(IG.v(500+0.1,500,0),IG.v(-1,0,0),0,0).clr(0);
new LineAgent(IG.v(0,500+0.1,0),IG.v(0,-1,0),0,0).clr(0);
new LineAgent(IG.v(500/2,0,0),IG.v(1,0,0),0,0).clr(0);
new LineAgent(IG.v(500,500/2,0),IG.v(0,1,0),0,0).clr(0);
new LineAgent(IG.v(500/2,500,0),IG.v(-1,0,0),0,0).clr(0);
new LineAgent(IG.v(0,500/2,0),IG.v(0,-1,0),0,0).clr(0);
for(int i=0; i < 30; i++){
new LineAgent(IRand.pt(100,100,0,400,400,0),IRand.pt(-10,-10,0,10,10,0),0,0).clr(IRand.clr(0.4,0.4,0.4));
}
}
static class LineAgent extends IAgent{
// constants
static final double length = 2;
static final double clearance = 1.99; //less than length
static final double angleThreshold = PI/20;
static final double threshold = 10;
static final int bendSize = 2;
IVec pt1, pt2;
boolean isColliding=false;
double angle=0;
double minDist=0;
double frontAngle=0;
double bendAngle=0;
int bendCount = 0;
LineAgent(IVec pt, IVec dir, double bend, int bcount){
pt1 = pt;
pt2 = pt.cp(dir.cp().len(length));
bendAngle = bend;
bendCount = bcount;
}
void interact(ArrayList < IDynamics > agents){
if(time == 0){ //only in the first time
minDist = -1; //reset
for(int i=0; i < agents.size() && !isColliding; i++){
if(agents.get(i) instanceof LineAgent){
LineAgent agent = (LineAgent)agents.get(i);
if(agent != this){ //agents include "this"
// checking clearance of end point
double dist = agent.pt2.dist(pt2);
if(dist < clearance){ isColliding=true; }
else if(dist < threshold){ //not colliding but close
if(!pt1.eq(agent.pt2) && //not the parent
pt2.dif(pt1).angle(agent.pt2.dif(pt1)) < angleThreshold && //in front
(minDist < 0 || dist < minDist) ){ //closest one
minDist = dist;
frontAngle = pt2.dif(pt1).angle(agent.pt2.dif(agent.pt1),IG.zaxis);
}
}
}
}
}
}
}
void update(){
if(time == 0){
if(isColliding){ del(); }
else{ //if not colliding
new ICurve(pt1,pt2).clr(clr());
IVec dir = pt2.dif(pt1);
if(IRand.pct(1)){ //branching
double r = red()+IRand.get(-0.1,0.1);
double g = green()+IRand.get(-0.1,0.1);
double b = blue()+IRand.get(-0.1,0.1);
new LineAgent(pt2, dir.cp().rot(IRand.get(PI/3,2*PI/3)), 0, 0).clr(r,g,b);
}
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);
//checking bend
if(bendCount == 0 && minDist >=0 && frontAngle!=0){
if(frontAngle < 0){ frontAngle+=PI; }//going in only one direction
bendCount = bendSize;
bendAngle = frontAngle/bendCount;
}
if(bendCount > 0){ //bending
dir.rot(bendAngle);
new LineAgent(pt2, dir, bendAngle, bendCount-1).clr(r,g,b);
}
else{ //go straight
new LineAgent(pt2, dir, 0, 0).clr(r,g,b);
}
}
}
}
}
HOME
FOR PROCESSING
DOWNLOAD
DOCUMENTS
TUTORIALS (Java /
Python)
GALLERY
SOURCE CODE(GitHub)
PRIVACY POLICY
ABOUT/CONTACT