//Josiah Greenewald (09588090) & Greg Keubler //final project // /////////////////////////////////////////// //global variables------------------------ int numberAgents; Agent a[]; Agent predator; boolean pursue, mouseUp, hunger; int n,u; float r; int time, hungerTime; int count; int target; float closestDist; int prey; float ang; color hungryColor; color neutralColor; color scaredColor; color deadColor; color selectedColor; BImage b; BImage wormL; BImage wormS; BImage predatorUp; BImage predatorDown; BImage death_pred; BImage blood_spot; BImage pred_select; BImage worm_sick_long; BImage worm_sick_short; BImage worm_hungry_long; BImage worm_hungry_short; BImage worm_scarred_long; BImage worm_scarred_short; BImage worm_sick_death; BImage pred_sick_up; BImage pred_sick_down; BImage pred_hungry_up; BImage pred_hungry_down; BImage pred_dead; BImage pred_model; BImage worm_model; ////////////////////////////////////////// void setup() { size(1200,600); background(255); framerate(30); //imageMode(CENTER_DIAMETER); b = loadImage("backgroundFinal.jpg"); background(b); wormL = loadImage("worm_long.gif"); wormS = loadImage("worm_short.gif"); predatorUp = loadImage("predator_up.gif"); predatorDown = loadImage("predator_down.gif"); death_pred = loadImage("death_pred.gif"); blood_spot = loadImage("blood_spot.gif"); pred_select = loadImage("pred_select.gif"); worm_sick_long = loadImage("worm_sick_long.gif"); worm_sick_short = loadImage("worm_sick_short.gif"); worm_hungry_long = loadImage("worm_hungry_long.gif"); worm_hungry_short = loadImage("worm_hungry_short.gif"); worm_scarred_long = loadImage("worm_scarred_long.gif"); worm_scarred_short = loadImage("worm_scarred_short.gif"); worm_sick_death = loadImage("worm_sick_death.gif"); pred_sick_up = loadImage("pred_sick_up.gif"); pred_sick_down = loadImage("pred_sick_down.gif"); pred_hungry_up = loadImage("pred_hungry_up.gif"); pred_hungry_down = loadImage("pred_hungry_down.gif"); pred_dead = loadImage("pred_dead.gif"); pred_model = loadImage("pred_model.jpg"); worm_model = loadImage("worm_model.jpg"); ellipseMode(CENTER_DIAMETER); hungryColor = color(255,0,0); neutralColor = color(0,255,100); scaredColor = color(25,0,255); deadColor = color(0,0,0); selectedColor = color(255,250,0); numberAgents = 25; a = new Agent[numberAgents]; predator = new Agent(new Position(random(20,780),random(20,480)), 0); predator.selected = true; pursue = false; n = 0; r = 40; time = 0; count = 0; mouseUp = false; target = 100; hunger = false; closestDist = 500; prey = 1; ang = 0; //set up the interface fill(255); rect(800,0,300,500); noFill(); stroke(0); strokeWeight(3); line(800,0,800,500); line(800,200,1100,200); strokeWeight(0); BFont metaBold; metaBold = loadFont("Meta-Bold.vlw.gz"); textFont(metaBold, 20); //text("word", 15, 50); setupAgents(); } //////////////////////////////////////////////////////////////////////// //set up the intitial positions void setupAgents() { for(int i=0, j=0; i 25) { dist = 25; } for(i=0; i (r/10)+1 && a[i].captured == false && a[i].dead == false && a[i].sick == false ) { a[i].scared = true; a[i].neutral = false; a[i].hungry = false; a[i].dead = false; a[i].sick = false; float head = findHeading(predator.location, a[i].location); float norm = normalizeHeading(head); //if not trapped against a wall then run away in the same direction you are being chased if(a[i].location.x>=40 && a[i].location.y>=40 && a[i].location.x<=860 && a[i].location.y<=560) { a[i].angle = head; // stroke(255); //strokeWeight(2); //line(a[i].location.x,a[i].location.y,a[i].location.displace(head,100).x,a[i].location.displace(head,100).y); a[i].location = a[i].location.displace(head,random(10,20)); } //if you are trapped against the wall run around the predator else if(a[i].location.x<40 || a[i].location.y<40 || a[i].location.x>860 || a[i].location.y>560) { a[i].angle = norm; //stroke(255); //strokeWeight(2); //line(a[i].location.x,a[i].location.y,a[i].location.displace(norm,100).x,a[i].location.displace(norm,100).y); a[i].location = a[i].location.displace(norm,random(10,20)); } else { Position center = new Position(800/2, 500/2); float centerHead = findHeading(a[i].location, center); a[i].angle = centerHead; //stroke(255); //strokeWeight(2); //line(a[i].location.x,a[i].location.y,a[i].location.displace(centerHead,100).x,a[i].location.displace(centerHead,100).y); a[i].location = a[i].location.displace(centerHead,random(10,15)); } //change color to scared color a[i].agentColor = scaredColor; while(a[i].angle > 360) a[i].angle -= 360; while(a[i].angle < 0) a[i].angle += 360; collisionCheck(i); if(i == target) { a[i].selected = true; a[i].drawScaredAgent(a[i].location, a[i].angle); } else { a[i].selected = false; a[i].drawScaredAgent(a[i].location, a[i].angle); } } //if you are captured then you are dead so stop and turn to dead color else if((dist(predator.location.x, predator.location.y, a[i].location.x, a[i].location.y) <= r || a[i].captured == true) && a[i].sickDead == false) { a[i].scared = false; a[i].neutral = false; a[i].hungry = false; a[i].dead = true; a[i].sick = false; a[i].captured = true; //u++; a[i].agentColor = deadColor; a[i].location = a[i].location; a[i].angle = a[i].angle; while(a[i].angle > 360) a[i].angle -= 360; while(a[i].angle < 0) a[i].angle += 360; if(i == target) { a[i].selected = true; a[i].drawDeadAgent(a[i].location, a[i].angle); } else { a[i].selected = false; a[i].drawDeadAgent(a[i].location, a[i].angle); } } else if(a[i].dead == true && a[i].captured == false && a[i].sickDead == true) { a[i].scared = false; a[i].neutral = false; a[i].hungry = false; a[i].dead = true; a[i].sick = false; a[i].location = a[i].location; a[i].angle = a[i].angle; if(i == target) { a[i].selected = true; a[i].drawDeadAgent(a[i].location, a[i].angle); } else { a[i].selected = false; a[i].drawDeadAgent(a[i].location, a[i].angle); } } else if((a[i].hungerCount > a[i].hungerLevel) && (a[i].captured == false) && ((dist(predator.location.x, predator.location.y, a[i].location.x, a[i].location.y) > 200) || predator.dead == true)) { a[i].neutral = false; a[i].sick = false; a[i].hungry = true; findFood(a[i]); if(i == target) { a[i].selected = true; a[i].drawHungryAgent(a[i].location,a[i].angle); } else { a[i].selected = false; a[i].drawHungryAgent(a[i].location,a[i].angle); } } else if(a[i].sick == true && a[i].captured == false && a[i].dead == false) { a[i].scared = false; a[i].neutral = false; a[i].hungry = false; a[i].dead = false; a[i].sick = true; diseased(a[i]); collisionCheck(i); if(i == target) { a[i].selected = true; a[i].drawSickAgent(a[i].location,a[i].angle); } else { a[i].selected = false; a[i].drawSickAgent(a[i].location,a[i].angle); } } //if you are not scared or captured else { //gives the agent a 20% chance to change direction when wandering if(check < 2) { a[i].angle += random(30); } else if(check >= 2 && check < 4) { a[i].angle -= random(30); } //if the agent has been eaten then keep wandering if(a[i].captured == false) { a[i].scared = false; a[i].neutral = true; a[i].hungry = false; a[i].dead = false; a[i].sick = false; //stroke(255); //strokeWeight(2); //line(a[i].location.x,a[i].location.y,a[i].location.displace(a[i].angle,100).x,a[i].location.displace(a[i].angle,100).y); a[i].location = a[i].location.displace(a[i].angle,distance); a[i].agentColor = neutralColor; collisionCheck(i); while(a[i].angle > 360) a[i].angle -= 360; while(a[i].angle < 0) a[i].angle += 360; if(i == target) { a[i].selected = true; a[i].drawAgent(a[i].location, selectedColor,a[i].angle); } else { a[i].selected = false; a[i].drawAgent(a[i].location, a[i].agentColor,a[i].angle); } } } } //predator is not pursueing if(pursue == false) { if(predator.sick == false && predator.dead == false) { predator.neutral = true; predator.hungry = false; predator.dead = false; predator.sick = false; //this makes it so the predator deosnt turn as much in wander mode if(random(1,10) < 5) { predator.angle += random(20); } else { predator.angle -= random(20); } //check if position is out of bounds if(predator.location.x<(r/2)-5 || predator.location.y<(r/2)-5 || predator.location.x>900-(r/2)+5 || predator.location.y>600-(r/2)+5) { Position center = new Position(800/2, 500/2); float centerHead = findHeading(predator.location, center); predator.angle = centerHead; predator.location = predator.location.displace(centerHead,10); } predator.location = predator.location.displace(predator.angle,random(5,10)); if(target == 100) { predator.selected = true; predator.drawPredator(predator.location, r, predator.angle); } else { predator.selected = false; predator.drawPredator(predator.location, r, predator.angle); } } else if(predator.sick == true) { predator.neutral = false; predator.hungry = false; predator.sick = true; if(predator.dead == true) { predator.neutral = false; predator.hungry = false; predator.dead = true; //predator.sick = false; predator.location = predator.location; predator.angle = predator.angle; if(predator.location.x<(r/2)-5 || predator.location.y<(r/2)-5 || predator.location.x>900-(r/2)+5 || predator.location.y>600-(r/2)+5) { Position center = new Position(800/2, 500/2); float centerHead = findHeading(predator.location, center); predator.angle = centerHead; predator.location = predator.location.displace(centerHead,10); } if(target == 100) { predator.selected = true; predator.drawDeadPredator(predator.location,r,predator.angle); } else { predator.selected = false; predator.drawDeadPredator(predator.location,r,predator.angle); } } else { predator.neutral = false; predator.hungry = false; predator.dead = false; predator.sick = true; diseased(predator); if(target == 100) { predator.selected = true; predator.drawSickPredator(predator.location,r,predator.angle); } else { predator.selected = false; predator.drawSickPredator(predator.location,r,predator.angle); } } } if((time%150 == 0) && (n <= a.length-1) && predator.sick == false && predator.dead == false) { pursue = true; time = 0; } } else if(predator.sick == false && pursue == true && predator.dead == false)//pursue = true { predator.neutral = false; predator.hungry = true; predator.dead = false; predator.sick = false; if(predator.location.x<(r/2)-5 || predator.location.y<(r/2)-5 || predator.location.x>900-(r/2)+5 || predator.location.y>600-(r/2)+5) { Position center = new Position(800/2, 500/2); float centerHead = findHeading(predator.location, center); predator.angle = centerHead; predator.location = predator.location.displace(centerHead,dist); } //-------------------------------------------------------- chaseAgent(predator,a[n].location); } } //checks for agent to agent collisions and wall collisions void collisionCheck(int i) { //check for agent to agent collisions for(int j=0; j=30 && a[i].location.y>=30 && a[i].location.x<=870 && a[i].location.y<=570) { a[i].angle = head; // stroke(255); //strokeWeight(2); //line(a[i].location.x,a[i].location.y,a[i].location.displace(head,100).x,a[i].location.displace(head,100).y); a[i].location = a[i].location.displace(head,random(10,15)); } //out of bounds else if(a[i].location.x<30 || a[i].location.y<30 || a[i].location.x>870 || a[i].location.y>570) { a[i].angle = norm; // stroke(255); // strokeWeight(2); //line(a[i].location.x,a[i].location.y,a[i].location.displace(norm,100).x,a[i].location.displace(norm,100).y); a[i].location = a[i].location.displace(norm,random(10,15)); } else { Position center = new Position(800/2, 500/2); float centerHead = findHeading(a[i].location, center); a[i].angle = centerHead; // stroke(255); // strokeWeight(2); // line(a[i].location.x,a[i].location.y,a[i].location.displace(centerHead,100).x,a[i].location.displace(centerHead,100).y); a[i].location = a[i].location.displace(centerHead,random(10,15)); } } } } //check if position is out of bounds if(a[i].location.x <= 30 || a[i].location.y <= 30 || a[i].location.x >= 870 || a[i].location.y >= 570) { Position center = new Position(800/2, 500/2); float centerHead = findHeading(a[i].location, center); a[i].angle = centerHead; a[i].location = a[i].location.displace(centerHead,random(10,15)); } } //gets the absolute heading between one position and another relative to the first float findHeading(Position p1, Position p2) { float angle = atan2(p2.y - p1.y, p2.x - p1.x); angle = (-1) * angle * (180/PI); if(p2.y >= p1.y) { angle = 360 - (angle*(-1)); } return angle; } //finds the normal to a heading float normalizeHeading(float angle_) { float rand = random(1,10); if(rand <= 5) angle_ -= 90; else angle_ += 90; return angle_; } void findFood(Agent agent_) { if(agent_.hungry = true) { float f1Dist = dist(agent_.location.x,agent_.location.y, random(10,120),random(10,120)); float f2Dist = dist(agent_.location.x,agent_.location.y, random(529,629),random(14,114)); float f3Dist = dist(agent_.location.x,agent_.location.y, random(758,858),random(473,573)); if(f1Dist <= f2Dist && f1Dist <= f3Dist) { agent_.angle = findHeading(agent_.location, new Position(random(10,120),random(10,120))); } else if(f2Dist < f1Dist && f2Dist <= f3Dist) { agent_.angle = findHeading(agent_.location, new Position(random(529,629),random(14,114))); } else { agent_.angle = findHeading(agent_.location, new Position(random(758,858),random(473,573))); } agent_.location = agent_.location.displace(agent_.angle,random(5,10)); if((agent_.location.x < 120 && agent_.location.y < 120) || (agent_.location.x > 758 && agent_.location.y > 473)) { agent_.hungerCount -= 2; if((agent_.hungerCount) < agent_.hungerLevel) { agent_.hungerCount = 0; agent_.hungry = false; } } else if(agent_.location.y < 114 && agent_.location.x > 529 && agent_.location.x < 629) { float check = random(10); agent_.hungerCount -= 2; if(check < 8 && (agent_.hungerCount) < agent_.hungerLevel) { agent_.sick = true; agent_.hungry = false; agent_.hungerCount = 0; } else if((agent_.hungerCount) < agent_.hungerLevel && check >= 8) { agent_.hungerCount = 0; agent_.hungry = false; } } } } void diseased(Agent agent_) { if(agent_.sick == true) { agent_.sickTime++; float num = random(0,8); if(num < 4) { agent_.angle += random(60); } else if(num < 7) { agent_.angle -= random(60); } else { agent_.angle = agent_.angle; } if(agent_.location.x <= 30 || agent_.location.y <= 30 || agent_.location.x >= 870 || agent_.location.y >= 570) { Position center = new Position(800/2, 500/2); float centerHead = findHeading(agent_.location, center); agent_.angle = centerHead; agent_.location = agent_.location.displace(centerHead,random(10,15)); } agent_.location = agent_.location.displace(agent_.angle, random(1,10)); if(agent_.sickTime > 90) { agent_.dead = true; agent_.sickDead = true; } } } //pursue another agent void chaseAgent(Agent predator_, Position p) { if(pursue == true) { float distance = 400/r; if(distance > 25) { distance = 25; } //float distance = 5; //-------------------------------------------- for(int y=0; y < numberAgents; y++) { if(dist(predator_.location.x,predator_.location.y, a[y].location.x,a[y].location.y) <= closestDist) { if(a[y].captured == false && a[y].sickDead == false && a[y].dead == false) { closestDist = dist(predator_.location.x,predator_.location.y, a[y].location.x,a[y].location.y); prey = y; /*if(closestDist < 50) { predator_.angle = findHeading(predator_.location, a[y].location); println("Y: "+y); }*/ //println("Prey: "+prey); //if(dist(predator_.location.x,predator_.location.y, a[y].location.x,a[y].location.y) > closestDist) //{ // break; //} //predator_.location = predator_.location.displace(predator_.angle,distance); } /* else { predator_.angle = findHeading(predator_.location, a[n].location); }*/ } /*else { if(a[n].captured == false) { predator_.angle = findHeading(predator_.location, a[prey].location); //closestDist = 30; //predator_.location = predator_.location.displace(predator_.angle,distance); } else { predator_.angle = findHeading(predator_.location, a[n].location); } }*/ } //predator_.angle = findHeading(predator_.location, a[prey].location); if(a[prey].captured == false && a[prey].sickDead == false && a[prey].dead == false) { predator_.angle = findHeading(predator_.location, a[prey].location); /*if(a[prey].captured == true) { predator_.angle = findHeading(predator_.location, new Position(800/2, 500/2)); }*/ } predator_.location = predator_.location.displace(predator_.angle,random(10,20)); closestDist = 800; //predator_.angle = findHeading(predator_.location, p); //predator_.location = predator_.location.displace(predator_.angle,distance); //check if position is out of bounds if(predator_.location.x<(r/2) || predator_.location.y<(r/2) || predator_.location.x>900 || predator_.location.y>600) { Position center = new Position(800/2, 500/2); float centerHead = findHeading(predator.location, center); predator.angle = centerHead; predator.location = predator.location.displace(centerHead,distance); } if((dist(predator.location.x, predator.location.y, a[prey].location.x, a[prey].location.y) <= r)) { n++; u++; if(a[prey].sick == true) { predator.sick = true; pursue = false; time = 0; } //double growth = 5.0/numberAgents; a[prey].captured = true; a[prey].dead = true; time = 0; if(n > a.length-1) { pursue = false; Position center = new Position(800/2, 500/2); predator_.angle = findHeading(predator_.location, center); } if(u > 4) { pursue = false; u = 0; } } /*else if(time%150 == 0 && n <= a.length-1) { //double decay = numberAgents/10.0; pursue = true; time = 0; }*/ //line(predator_.location.x,predator_.location.y,p.x,p.y); if(target == 100) { predator.selected = true; predator_.drawHungryPredator(predator_.location, r, predator.angle); } else { predator.selected = false; predator_.drawHungryPredator(predator_.location, r, predator.angle); } } else//pursue = false { randomMove(); } } ////////////////////////////////////////// class Agent { Position location; float angle; boolean captured; color agentColor; boolean isDead; float hungerLevel; boolean hungry, scared, dead, sick, neutral, sickDead, selected; int hungerCount, sickTime; //Constructors---------------------------- //Default Constructor: Agent() { location.x = 800/2; location.y = 500/2; angle = 0; captured = false; isDead = false; agentColor = neutralColor; hungerLevel = random(100,600); hungerCount = 0; sickTime = 0; hungry = false; scared = false; dead = false; sickDead = false; sick = false; neutral = true; selected = false; drawAgent(location, agentColor, angle); } //Overloaded Constructor: Agent(Position location_, float angle_) { location = location_; angle = angle_; captured = false; isDead = false; agentColor = neutralColor; drawAgent(location, agentColor, angle); hungerLevel = random(100,600); hungerCount = 0; sickTime = 0; hungry = false; scared = false; dead = false; sick = false; neutral = true; sickDead = false; selected = false; } //Copy Constructor: Agent(Agent agent_) { location = agent_.location; angle = agent_.angle; captured = false; isDead = false; agentColor = neutralColor; drawAgent(location, agentColor, angle); hungerLevel = random(100,600); hungerCount = 0; sickTime = 0; hungry = false; scared = false; dead = false; sick = false; neutral = true; sickDead = false; selected = false; } //Utility Functions----------------------- //draw a single agent void drawAgent(Position location_, color c, float heading) { if(selected == true) { push(); imageMode(CENTER_DIAMETER); translate(location_.x,location_.y); rotate(-radians(heading)); tint(246,255,0,100); image(pred_select,0,0); noTint(); if(time%3 == 0) image(wormL,0,0); else image(wormS,0,0); pop(); } else { push(); imageMode(CENTER_DIAMETER); translate(location_.x,location_.y); rotate(-radians(heading)); if(time%3 == 0) image(wormL,0,0); else image(wormS,0,0); pop(); } } void drawSickAgent(Position location_,float heading) { if(selected == true) { push(); imageMode(CENTER_DIAMETER); translate(location_.x,location_.y); rotate(-radians(heading)); tint(246,255,0,100); image(pred_select,0,0); noTint(); if(time%3 == 0) { translate(2,2); image(worm_sick_long,0,0); } else { translate(-2,-2); rotate(-radians(heading)); image(worm_sick_short,0,0); } pop(); } else { push(); imageMode(CENTER_DIAMETER); translate(location_.x,location_.y); rotate(-radians(heading)); if(time%3 == 0) { translate(2,2); image(worm_sick_long,0,0); } else { translate(-2,-2); rotate(-radians(heading)); image(worm_sick_short,0,0); } pop(); } } void drawHungryAgent(Position location_,float heading) { if(selected == true) { push(); imageMode(CENTER_DIAMETER); translate(location_.x,location_.y); rotate(-radians(heading)); tint(246,255,0,100); image(pred_select,0,0); noTint(); if(time%3 == 0) { image(worm_hungry_long,0,0); } else { image(worm_hungry_short,0,0); } pop(); } else { push(); imageMode(CENTER_DIAMETER); translate(location_.x,location_.y); rotate(-radians(heading)); if(time%3 == 0) { image(worm_hungry_long,0,0); } else { image(worm_hungry_short,0,0); } pop(); } } void drawScaredAgent(Position location_,float heading) { push(); imageMode(CENTER_DIAMETER); translate(location_.x,location_.y); rotate(-radians(heading)); if(selected == true) { tint(246,255,0,100); image(pred_select,0,0); noTint(); } if(time%3 == 0) { image(worm_scarred_long,0,0); } else { image(worm_scarred_short,0,0); } pop(); } void drawDeadAgent(Position location_,float heading) { push(); imageMode(CENTER_DIAMETER); translate(location_.x,location_.y); rotate(-radians(heading)); if(selected == true) { tint(246,255,0,100); image(pred_select,0,0); noTint(); } tint(200,0,0,100); image(blood_spot,0,0); noTint(); if(captured == false) image(worm_sick_death,0,0); else if(captured == true) image(death_pred,0,0); pop(); } void drawPredator(Position location_, float radius, float heading) { if(target == 100) { push(); imageMode(CENTER_DIAMETER); translate(location_.x,location_.y); rotate(-radians(heading)); if(selected == true) { tint(246,255,0,100); image(pred_select,0,0); noTint(); } if(time%5 <= 2) image(predatorDown,0,0); else image(predatorUp,0,0); pop(); } else { push(); imageMode(CENTER_DIAMETER); translate(location_.x,location_.y); rotate(-radians(heading)); if(selected == true) { tint(246,255,0,100); image(pred_select,0,0); noTint(); } if(time%5 <= 2) image(predatorDown,0,0); else image(predatorUp,0,0); pop(); } } void drawHungryPredator(Position location_, float radius, float heading) { push(); imageMode(CENTER_DIAMETER); translate(location_.x,location_.y); rotate(-radians(heading)); if(selected == true) { tint(246,255,0,100); image(pred_select,0,0); noTint(); } if(time%5 <= 2) { image(pred_hungry_up,0,0); } else { image(pred_hungry_down,0,0); } pop(); } void drawSickPredator(Position location_, float radius, float heading) { push(); imageMode(CENTER_DIAMETER); translate(location_.x,location_.y); rotate(-radians(heading)); if(selected == true) { tint(246,255,0,100); image(pred_select,0,0); noTint(); } if(time%3 == 0) { image(pred_sick_up,0,0); } else { rotate(radians(heading)); image(pred_sick_down,0,0); } pop(); } void drawDeadPredator(Position location_, float radius, float heading) { push(); imageMode(CENTER_DIAMETER); translate(location_.x,location_.y); //rotate(-radians(heading)); if(selected == true) { tint(246,255,0,100); image(pred_select,0,0); noTint(); } image(pred_dead,0,0); pop(); } } ////////////////////////////////////////// class Position { float x,y; //Constructors---------------------------- //Default Constructor: Position() { x = 0; y = 0; } //Overloaded Constructor: Position(float x_, float y_) { x = x_; y = y_; } //Copy Constructor: Position(Position p_) { x = p_.x; y = p_.y; } //Accessor Functions---------------------- //returns the current position Position getPosition() { return new Position(x,y); } //Modifier Functions---------------------- //sets the position void setPosition(float x_,float y_) { x = x_; y = y_; } //Utility Functions----------------------- //returns the position displaced by an angle and distance Position displace(float angle_, float distance) { Position newPos = new Position(x,y); newPos.x += (cos(radians(angle_))*distance); newPos.y -= (sin(radians(angle_))*distance); return newPos; } } ////////////////////////////////////////// //////////////////////////////////////////