xxxxxxxxxx
// Predator Prey simulation
// original author: Matthew Conroy -- June 2010
// http://www.openprocessing.org/sketch/10461
// shared under Creative Commons license
// https://creativecommons.org/licenses/by-nc-sa/3.0/
// altered by: Jason Galbraith -- August 2015
/*
**************************************************************
Change the numbers below to see how it changes the simulation!
**************************************************************
*/
//These are the starting number of prey and predators when
//the simulation first starts.
int numberOfPreds=500;
int numberOfPrey=500;
//This is the fastest speed that predators and prey can run.
//Increasing this number makes them have a quicker maximum speed!
float predSpeedLimit=1.5;
float preySpeedLimit=10.5;
//This is how old prey must be before they reproduce
float preyBirthTime = 3.0;
//This is how old predators must be before they reproduce
float predsBirthTime = 2.4;
//This is how long predators can last before they die of hunger.
float predsHungerTime = 2.2;
//This is the maximum number of prey that can exist in the simulation.
float preyPopCap = 4000;
//Predators will kill prey that are within this distance (in pixels).
//Increasing this number will allow predators to kill prey that are
//farther away.
float killThresholdDist = 4.5;
//Population sampling is how often to plot points for the graph.
//A population sampling of one will plot very quickly, but not
//have a lot of long-term data. Sampling every ten will take longer,
//but have more of a history.
int populationSample = 5;
/*
****************************************************************
Below here is the actual simulation. You probably shouldn't mess
with this section. Or at least, you should expect weird results.
****************************************************************
*/
PImage canvas1;
int[] popPrey;
int[] popPreds;
int popHistory=600;
int popSteps=10;
int popCount=0;
int popCountBeginning=0;
int popPreyAve=0;
int popPredsAve=0;
int sampleCount = populationSample - 1;
int maxPop = numberOfPreds;
color predsColor=color(200,100,255);
color preyColor=color(255,255,255);
color referenceColor=color(0,255,0);
int enviroHeight=500;
int numberOfBalls=300;
float paramScale=0.4;
float preyBirthAge = preyBirthTime*paramScale;
float predsBirthAge = predsBirthTime*paramScale;
float predsHungerLimit = predsHungerTime*paramScale;
int radii=2;
float time=0;
float timeStep=0.01;
ArrayList<PPBall> preds;
ArrayList<PPBall> prey;
Vect2D[] vels;
Vect2D[] accels;
int[] closest = new int[numberOfBalls];
PFont f;
void setup (){
size(600, 650);
canvas1 = createImage(600,600,RGB);
f = createFont("Impact",32);
frameRate(200);
preds = new ArrayList<PPBall>();
prey = new ArrayList<PPBall>();
popPrey = new int[popHistory];
popPreds = new int[popHistory];
// set up predators
for(int i=0; i<numberOfPreds; i++) {
Vect2D vv;
Vect2D aa;
vv = new Vect2D(0.0,0.0);
aa = new Vect2D(0.0,0.0);
float fract=0.3;
preds.add(new PPBall(random(width*fract,width*(1-fract)),random(height*fract,height*(1-fract)),radii*1.,random(predsHungerLimit*0.8),vv,aa,0,random(predsBirthAge*0.9)));
}
// set up prey
for(int i=0; i<numberOfPrey; i++) {
float fract=0.25;
Vect2D vv;
Vect2D aa;
vv = new Vect2D(0.0,0.0);
aa = new Vect2D(0.0,0.0);
fract=0.3;
prey.add(new PPBall(random(width*fract,width*(1-fract)),random(height*fract,height*(1-fract)),radii*1.,random(preyBirthAge*0.8),vv,aa,0,0));
}
}
void draw(){
smooth();
time=time+timeStep;
background(0);
adjustPositions(preds);
adjustPositions(prey);
// the prey give birth
for(int i=0; i<prey.size(); i++) {
PPBall temp = (PPBall) prey.get(i);
if (temp.a>preyBirthAge) {
PPBall baby;
Vect2D vv;
Vect2D aa;
vv = new Vect2D(0.0,0.0);
aa = new Vect2D(0.0,0.0);
if (random(1)>sq(prey.size()/preyPopCap)) { // live birth more likely when it is not crowded
prey.add(new PPBall(temp.x,temp.y,temp.r,random(preyBirthAge*0.2),vv,aa,0,0));
}
prey.set(i,temp);
temp.a=random(preyBirthAge*0.1);
}
}
// the preds give birth
for(int i=0; i<preds.size(); i++) {
PPBall temp = (PPBall) preds.get(i);
if (temp.birthTime>predsBirthAge) {
PPBall baby;
Vect2D vv;
Vect2D aa;
vv = new Vect2D(0.0,0.0);
aa = new Vect2D(0.0,0.0);
preds.add(new PPBall(temp.x,temp.y,temp.r,0,vv,aa,0,random(predsBirthAge*0.2)));
preds.set(i,temp);
temp.birthTime=0;
}
}
// draw preds
for(int i=0; i< preds.size(); i++) {
PPBall temp=(PPBall) preds.get(i);
fill(predsColor);
stroke(predsColor);
ellipse(temp.x, temp.y, temp.r*2, temp.r*2);
}
// draw prey
for(int i=0; i< prey.size(); i++) {
PPBall temp=(PPBall) prey.get(i);
noFill();
stroke(preyColor);
ellipse(temp.x, temp.y, temp.r*2, temp.r*2);
}
// kill the preds
for(int i=preds.size()-1; i>=0; i--) {
PPBall temp= preds.get(i);
if (temp.hunger>predsHungerLimit) {
preds.remove(i);
}
}
// kill the prey
int isClose=0;
int j=0;
for(int i=prey.size()-1; i>=0; i--) {
isClose=0;
j=0;
PPBall tempPrey = prey.get(i);
while((isClose==0) && j<preds.size()) {
PPBall tempPred= preds.get(j);
if(dist(tempPrey.x,tempPrey.y,tempPred.x,tempPred.y) < killThresholdDist) {
isClose=1;
tempPred.hunger=0; // this one just ate
preds.set(j,tempPred);
}
++j;
}
if (isClose==1) { prey.remove(i);
}
}
adjustVelocities13(preds,prey);
// keep track of populations
popPredsAve += preds.size();
popPreyAve += prey.size();
sampleCount++;
if (sampleCount == populationSample) {
sampleCount = 0;
popCount++;
if (popCount < popHistory) {
popPrey[popCount] = prey.size();
popPreds[popCount] = preds.size();
}
else if (popCount>=popHistory) {
for(int i = 0; i < popPrey.length - 1; i++){
popPrey[i] = popPrey[i+1];
popPreds[i] = popPreds[i+1];
}
popPrey[popHistory-1] = prey.size();
popPreds[popHistory-1] = preds.size();
popPredsAve=0;
popPreyAve=0;
popCountBeginning++;
}
}
//plot population data
int maxIndex = 0;
maxPop = popPrey[0];
for (int i =0; i < popPrey.length; i++){//find max Prey
if (popPrey[i] > maxPop && i < popCount) {
maxIndex = i;
maxPop = popPrey[i];
}
if (popPreds[i] > maxPop && i < popCount) {
maxIndex = i;
maxPop = popPreds[i];
}
}
for(int i=0; i<popPrey.length;i++) {//Plot the points
stroke(preyColor);
float popY=0;
popY=popToY(popPrey[i]);
point(i,popY);
popY = popToY(popPreds[i]);
stroke(predsColor);
point(i,popY);
}
stroke(referenceColor);//plot the labels and lines
fill(referenceColor);
textFont(f,16);
text("max:"+round(max(popPrey[maxIndex], popPreds[maxIndex])), 10, popToY(max(popPrey[maxIndex],popPreds[maxIndex])));
line(0,popToY(max(popPrey[maxIndex], popPreds[maxIndex])),600,popToY(max(popPrey[maxIndex], popPreds[maxIndex])));
textFont(f,32);
fill(predsColor);
text("PREDATORS:"+preds.size(),10,height - 120);
fill(preyColor);
text("PREY:"+prey.size(),width-200,height - 120);
} // end draw
float popToY(float x) {//Adjust y positions of graph based on max population
return(height-5-(95*(x/(maxPop))));
}
void births(PPBall[] balls) {//Create new ball objects
for(int i=0; i<balls.length; i++) {
if (balls[i].a>1) {
balls[i].a=0;
PPBall baby;
Vect2D vv;
Vect2D aa;
vv = new Vect2D(0.0,0.0);
aa = new Vect2D(0.0,0.0);
baby = new PPBall(balls[i].x,balls[i].y,balls[i].r,0,vv,aa,0,0);
balls = (PPBall[]) append(balls,baby);
}
}
}
void adjustPositions(ArrayList balls) {//Move all the ball objects
for (int i=0; i<balls.size(); i++) {
PPBall temp=(PPBall) balls.get(i);
temp.x += temp.velocity.vx;
temp.y += temp.velocity.vy;
if (temp.x<0) { temp.x=temp.x+width; }
if (temp.x>width) { temp.x=temp.x-width; }
if (temp.y<0) { temp.y=temp.y+enviroHeight; }
if (temp.y>enviroHeight) { temp.y=temp.y-enviroHeight; }
temp.a += timeStep;
temp.hunger += timeStep;
temp.birthTime += timeStep;
balls.set(i,temp);
}
}
void speedLimit(Vect2D vels,float speedLimit) {//Add speed limit
float speed = dist(0,0,vels.vx,vels.vy);
if (speed>speedLimit) {
vels.vx = speedLimit*vels.vx/speed;
vels.vy = speedLimit*vels.vy/speed;
}
}
void adjustVelocities13(ArrayList preds, ArrayList prey) {//Adjust all the velocities
for(int i=0; i< preds.size(); i++) {
PPBall temp=(PPBall) preds.get(i);
temp.velocity.vx += random(-0.1,0.1);
temp.velocity.vy += random(-0.1,0.1);
speedLimit(temp.velocity,predSpeedLimit);
preds.set(i,temp);
}
for(int i=0; i< prey.size(); i++) {
PPBall temp=(PPBall) prey.get(i);
temp.velocity.vx += random(-0.1,0.1);
temp.velocity.vy += random(-0.1,0.1);
speedLimit(temp.velocity,preySpeedLimit);
prey.set(i,temp);
}
}
class PPBall{//Object representing a predator or prey
float x, y, r, a, hunger,birthTime;
Vect2D velocity;
Vect2D acceleration;
// default constructor
PPBall() {
}
PPBall(float x, float y, float r, float a, Vect2D velocity, Vect2D acceleration, float hunger, float birthTime) {
this.x = x;
this.y = y;
this.r = r;
this.a = a; //age
this.velocity = velocity;
this.acceleration = acceleration;
this.hunger = hunger; // time since last eat (for predators)
this.birthTime = birthTime; // time since last birth
}
}
class Vect2D{//Two dimensional vector in combonent form
float vx, vy;
// default constructor
Vect2D() {
}
Vect2D(float vx, float vy) {
this.vx = vx;
this.vy = vy;
}
}