class Animal extends Cell implements Runnable
{
protected float maxSpeed, sensoryRange;
public Brain myBrain;
//public PVector velocity;
float carn;
public Animal()
{
super();
//velocity = new PVector();
maxSpeed = modify(2);
sensoryRange = modify(50);
carn = random(-.1,.2);
myBrain = new Brain(this);
calcCost();
}
public Animal(Animal parent)
{
super(parent);
//velocity = new PVector();
maxSpeed = modify(parent.maxSpeed);
sensoryRange = modify(parent.sensoryRange);
carn = parent.carn;
if((carn == 0 || carn == 1 && random(1) < .3) || !(carn == 0 || carn == 1))
carn += randomNormal() * .3;
myBrain = parent.myBrain.makeChild(this);
calcCost();
}
// return a random value in the range [0..1] with normal distribution around 0.
// Implements the Marsaglia Polar Method, as described in wikipedia, but only returns one of the values.
float randomNormal()
{
float x = 1.0, y = 1.0, s = 2.0; // s = x^2 + y^2
while(s >= 1.0)
{
x = random(-1.0f, 1.0f);
y = random(-1.0f, 1.0f);
s = x*x + y*y;
}
return x * sqrt(-2.0f * log(s)/s);
}
/*
public Animal(Animal m, Animal d)//sexual reproduction
{
super(m,d);
maxSpeed = modify(m.maxSpeed+d.maxSpeed)/2;
sensoryRange = modify(m.sensoryRange+d.sensoryRange)/2;
carn = modify(m.carn+d.carn)/2;
b = new Brain(this,(Brain)m.b);//this would get your brain only from your mom. may be bad.
checkVals();
}
*/
private void calcCost()
{
carn = constrain(carn,0,1);
livingCost += (myDish.animalCostMod/200) + (sensoryRange/500) + (maxSpeed/1000);
}
public void run()
{
Dish nearbyCells = new Dish();
for(int k = 0; k < myDish.size(); k++)
if(dist(myDish.get(k)) < effectiveSensoryRange())
nearbyCells.add(myDish.get(k));
move(myBrain.move(nearbyCells));
if(touchingCells.size() > 0)//if there are some adjacent cells, eat one of them
{
Cell best = touchingCells.get(0);
for(int k = 1; k < touchingCells.size(); k++)
{
Cell c = touchingCells.get(k);
if(myBrain.goodToEat(c) && amtGained(c) > amtGained(best))
best = c;
}
if(myBrain.goodToEat(best))
{
w += amtGained(best);
best.sub(amtEaten(best));
}
}
if(carn == 0)
myColor = color(70,300,360*w/maxSize);
else if(carn == 1)
myColor = color(-10,360,360*w/maxSize);
else
myColor = color(60*(1.0-carn),360,360*w/maxSize);
//loc.add(velocity);
//velocity.div(100);
super.run();
}
public float amtGained(Cell c)
{
if(c instanceof Animal)
return amtEaten(c) * .8*carn;
else//if its a plant
return amtEaten(c) * .25*sqrt(1.0-carn);
}
public float amtEaten(Cell c)
{
float eaten;
if(c instanceof Animal)
if(carn == 1)
eaten = (carn*8) + 1;
else
eaten = (carn*5) + 1 - c.def;
else//if its a plant
if(carn == 0)
eaten = 4;
else
eaten = 3.5 - c.def;
return constrain(eaten, 0, c.w);
}
protected void mouseOver()
{
fill(255,0);
strokeWeight(.3);
ellipse(effectiveSensoryRange()*2);
super.mouseOver();
if(mouseEvent != null && mouseEvent.getClickCount()==2)//double click
{
myBrain = new BrainManual(this);
//paused = false;
//b.move(new ArrayList());
zoom = .5*width / effectiveSensoryRange();
((Dish)dishes.get(0)).loc = PVector.mult(loc,-1);//places the camera directly above the controlled cell
}
}
/*
Moves the cell a distance determined by the PVector parameter.
Decreases the size of the cell based on the distance moved.
*/
protected void move(PVector v)
{
v.limit(maxSpeed);
w -= sq(v.mag()) / 50;
v.div(myDish.viscosity);
loc.add(v);
//velocity.add(v);
loc.limit(radius);
}
public float effectiveSensoryRange()
{
return 2*sqrt(w) + sensoryRange*myDish.visibility;
}
public String toString()
{
return " maxSpeed: "+maxSpeed+" sensoryRange: "+sensoryRange+" carn: "+carn+super.toString()+myBrain.toString();
}
}
public class Brain
{
protected Animal a;//the animal that the brain is controlling
//protected ArrayList mem;//you can store previous good feeding locations here
protected Cell target;
protected Animal predator;
protected float minDist;//the min dist between the predator and the prey, before the brain will choose to run from the predator instead of go for the food
protected int marker;//for recognizing relatives, so as not to eat them //Is this working or not?!?!?!?!?!
public Brain(Animal body)//body is the animal that the brain is controlling
{
a = body;
target = a;
predator = a;
minDist = random(0,body.effectiveSensoryRange()*2);
marker = (int)random(100,1000);
}
public Brain makeChild(Animal childBody)
{
Brain b = new Brain(childBody);
b.minDist = a.modify(minDist);
b.marker = marker;
if(random(1) < .1)
b.marker = (int)a.modify(marker);
return b;
}
/*
public Animal goodBody()
{
Animal a = new Animal();
return a;
}
*/
public PVector move(Dish cells)
{
if(cells.size() == 0)
return PVector.sub(target.loc,a.loc);
if(a.dist(target) > a.effectiveSensoryRange() * 2 || target.w <= 0)//you can track a single target to 2 times your sensory range
target = a;
if(a.dist(predator) > a.effectiveSensoryRange() || predator.w <= 0)
predator = a;
for(int k = 0 ; k < cells.size(); k++)
{
Cell c = cells.get(k);//(int)random(cells.size()-1));
if(targetQuality(c) > targetQuality(target) && goodToEat(c))
target = c;//set it as the new target
if(c instanceof Animal)//then check for predators
{
Animal threat = (Animal) c;
if(threat.myBrain.targetQuality(a) > predator.myBrain.targetQuality(a) && threat.myBrain.goodToEat(a))// && a.carn > predator.carn)
predator = threat;//set it as the new predator
}
}
if(predator != a && predator.dist(target) < minDist)
return PVector.mult(PVector.sub(a.loc,predator.loc),100);//run from the predator
else
return PVector.sub(target.loc,a.loc);//chase the prey
}
public float targetQuality(Cell c)//returns a value aproximating the benefit of going after c
{
if(!goodToEat(c))
return 0;
if(c instanceof Animal)
return c.w * (a.amtGained(c) - ((Animal)c).amtEaten(a)) / (100+a.dist(c)-sqrt(c.w));
else//if its a plant
return a.amtGained(c) / (100+a.dist(c)-sqrt(c.w));
}
public boolean goodToEat(Cell c)
{
return c != a && !(c instanceof Animal && ((Animal)c).myBrain.marker == marker);
}
/*
//returns true if this Animal agrees to attack the target, false otherwise
public Boolean sendTarget(Cell c)
{
return false;
}
public void sendPredator(Animal a)//a is the predatory animal which you are worning this Animal of.
{
}
public void sendFood(int amount, Animal sender)
{
a.w += amount;
sender.w -= amount;
}
*/
public String toString()
{
return "";
}
}
public class BrainManual extends Brain
{
public BrainManual(Animal body)
{
super(body);
}
public BrainManual(Animal body, Brain parent)
{
this(body);
}
public PVector move(Dish cells)
{
zoom = width / (a.effectiveSensoryRange()*2);
a.myDish.loc = PVector.mult(a.loc,-1);//places the camera directly above the controlled cell
PVector move = PVector.sub(cursor,a.myDish.loc);
move.sub(a.loc);
move.div(10);
return move;
/*
a.mouseOver();
/*
fill(255,10);
strokeWeight(10);
stroke(255);
ellipse(ORIGIN,a.effectiveSensoryRange()*2);
*/
/*
PVector move;
if(mousePressed)
target = PVector.sub(cursor,a.myDish.loc);
if(target == null)
{
move = cursor.get();
move.sub(a.myDish.loc);
move.sub(a.loc);
move.div(5);
}
else
{
ellipse(target,10);
move = PVector.sub(target,a.loc);
if(a.loc.equals(target));
target = null;
}
return move;
*/
}
}
class Cell implements Runnable
{
protected PVector loc;//the location of the cell relative to the center of the dish
public float w, maxSize, def;
protected color myColor;//the color of the cell (red-yellow for animals, green for plants, grey for rocks)
protected Dish myDish;//the dish that contains this cell
protected float livingCost;//the amount of energy lost each time run is called
protected Dish touchingCells;
public Cell()
{
myDish = new Dish();
int r = (int)random(radius/2);
float theta = random(TWO_PI);
loc = new PVector(cos(theta),sin(theta));
loc.mult(r);
maxSize = random(20,60);
w = maxSize/2;
def = random(.2);
touchingCells = new Dish();
calcCost();
}
public Cell(Cell parent)//bianry fission
{
myDish = parent.myDish;
myDish.add(this);
loc = parent.loc.get();
w = parent.w / 2;
maxSize = modify(parent.maxSize-20) + 20;
def = modify(parent.def);
touchingCells = new Dish();
calcCost();
}
/*
public Cell(Cell m, Cell d)//sexual reproduction
{
myDish = m.myDish;
loc = m.loc.get();
w = m.w * .3;//you get a fraction of your mom's weight
calcCost();
}
*/
private void calcCost()
{
livingCost = def*myDish.defMod/2;
myDish.add(this);
}
public void show()
{
pushMatrix();
translate(loc);
stroke(200);
strokeWeight(def/2);
fill(myColor);
ellipse(sqrt(w)*1.5);//draw the cell
if(!(w > -10000))//if w is Not A Number
{
fill(255,80);
ellipse(10);
}
if(loc.dist(PVector.sub(cursor,myDish.loc)) < sqrt(w) && !mousePressed)
mouseOver();
popMatrix();
}
protected void mouseOver()
{
scale(1.5);
strokeWeight(.3);
fill(255,0);
ellipse(sqrt(10));
ellipse(sqrt(maxSize));
/*
PVector pmouse = new PVector((pmouseX-centerX)/zoom,(pmouseY-centerY)/zoom);
if(loc.dist(pmouse) > sqrt(w))
println(this);
*/
}
public void run()
{
push();
sub(livingCost);
if(w > maxSize)//if you are too big, split.
{
if(this instanceof Animal && myDish.animalWeight() == w && dishes.size() == 1)
println("Founder Effect!");
Cell c1;
Cell c2;
if(this instanceof Plant)
{
Plant parent = (Plant)this;
c1 = new Plant(parent);
c2 = new Plant(parent);
}
else// if(this instanceof Animal)
{
Animal parent = (Animal)this;
c1 = new Animal(parent);
c2 = new Animal(parent);
if(parent.myBrain instanceof BrainManual)
{
//paused = true;
((Animal)c1).myBrain = new BrainManual((Animal)c1);
}
}
float angle = random(TWO_PI);//radians
PVector v = new PVector(sin(angle),cos(angle));
v.mult(sqrt(w));
c1.loc.add(v);
c2.loc.sub(v);
die();
}
else if(w < 10)
{
if(this instanceof Animal && ((Animal)this).myBrain instanceof BrainManual)
{
zoom = 2;
myDish.loc = ORIGIN.get();
}
die();
}
}
public void push()
{
if(random(1) < .1 || this instanceof Animal)
updateTouchingCells();
for(int k = 0; k < touchingCells.size(); k++)
{
Cell c = touchingCells.get(k);
if(touching(c))
{
PVector push = PVector.sub(c.loc,loc);
push.normalize();
push.mult((sqrt(w) + sqrt(c.w) - dist(c))/2);
c.loc.add(push);
if(!(c instanceof Animal && this instanceof Plant))
c.sub(push.mag() * 2);
}
else
touchingCells.remove(c);
}
}
/*
public void updateTouchingCellsFromTouching()
{
for(int t = 0; t < touchingCells.size(); t++)
{
Cell c = touchingCells.get(t);
for(int k = 0; k < c.touchingCells.size(); k++)
if(touching(c) && !(c instanceof Rock))
touchingCells.add(c);
}
}
*/
public void updateTouchingCells()
{
touchingCells = new Dish();
for(int k = 0; k < myDish.size(); k++)
{
Cell c = (Cell)myDish.get(k);
if(touching(c) && !(c instanceof Rock))
touchingCells.add(c);
}
}
public void sub(float amount)
{
w -= amount;
if(w < 0)
{
w = 0;
die();
}
}
public float dist(Cell c)//returns the distance to another Cell
{
return loc.dist(c.loc);
}
public float modify(float num)
{
return num * pow(1.5,random(-1, 1));
}
protected void die()
{
myDish.remove(this);
}
public String toString()
{
return " w:" +w+" loc:"+loc+" maxSize:"+maxSize+" def:"+def;
}
public boolean touching(Cell c)
{
return dist(c) < sqrt(w) + sqrt(c.w) && c != this;
}
}
class Dish implements Runnable
{
private PVector loc;
private ArrayList cells;
//static float radius = 160;
private static final float sunlight = 1;
private float animalCostMod, defMod, viscosity, visibility;
public float progress;//the progress of the dish to splitting
/*
static
{
radius = 160;
}
*/
public Dish()
{
/*
if(dishes.size() > 0)
radius = ((Dish)dishes.get(0)).radius;
else
radius = 160;
*/
loc = ORIGIN.get();//cursor.get();
cells = new ArrayList();
animalCostMod = modify(1);
defMod = modify(1);
visibility = modify(1);
viscosity = modify(1);
progress = 0;
}
public Dish(int plants,int animals)
{
this();
for(int p = 0; p < plants; p++)
add(new Plant());
for(int a = 0; a < animals; a++)
add(new Animal());
for(int k = 0; k < cells.size(); k++)
get(k).myDish = this;
}
public Dish(int plants, int animals, int rocks)
{
this(plants,animals);
for(int r = 0; r < rocks; r++)
add(new Rock());
for(int k = 0; k < cells.size(); k++)
get(k).myDish = this;
}
public Dish(Dish p)//only for dish evolution mode, has glithces
{
this();
loc = p.loc.get();
//sunlight = modify(p.sunlight);
animalCostMod = modify(p.animalCostMod);
defMod = modify(p.defMod);
visibility = modify(p.visibility);
viscosity = modify(p.viscosity);
}
public float modify(float num)
{
return num * pow(1.3,random(-1, 1));
}
public void run()
{
/*
PVector grav = PVector.sub(ORIGIN,loc);//makes all the dishes fall to the center of the screen
grav.limit(1);
loc.add(grav);
*/
for(int k = 0; k < cells.size(); k++)
((Cell)get(k)).run();//runs the cells
if(dishEvolution)
{
progress += (quality()-avgQuality())/100;
if(progress > TWO_PI)
{
if(dishes.size() != 1)
killWorstDish();
devide();
}
//else if(progress < 0)
//progress = 0;
}
if(animalWeight() <= 0 || plantWeight() <= 0)
die();
for(int k = 0; k < dishes.size(); k++)
{
Dish d = (Dish)dishes.get(k);
if(touching(d))
{
if(dist(d) == 0 && d != this)
d.loc.add(new PVector(random(-1,1),random(-1,1)));//radius));//adds a small random vector, so that the distance wont be 0.
PVector push = PVector.sub(d.loc,loc);
push.limit((1+(2*radius) - dist(d))/3.0);
d.loc.add(push);
}
}
}
public void show()
{
translate(loc);
int s = size();
PVector v = new PVector();
for(int k = 0; k < s; k++)
{
color c = get(k).myColor;
PVector values = new PVector(red(c),green(c),blue(c));
if(get(k) instanceof Animal)
values.mult(5);
v.add(values);
}
v.div(s);
color avg = color(v.x, v.y, v.z);
fill(hue(avg),100/zoom,365,50);
stroke(200);
strokeWeight(10);
ellipse(radius*2);
for(int k = 0; k < cells.size(); k++)
((Cell)get(k)).show();//shows all the cells
if(progress > 0 && dishEvolution)
{
fill(255,0);
strokeWeight(10);
stroke(255);
arc(0, 0, radius*2, radius*2, -PI/2, progress - PI/2);
}
}
public float avgAnimalWeight()
{
float weight = 0;
for(int k = 0; k < dishes.size(); k++)
{
Dish d = (Dish)dishes.get(k);
weight += d.animalWeight();
}
return weight/dishes.size();
}
public float avgQuality()
{
float total = 0;
for(int k = 0; k < dishes.size(); k++)
{
Dish d = (Dish)dishes.get(k);
total += d.quality();
}
return total/dishes.size();
}
public float quality()
{
float score = 0;
for(int k = 0; k < size(); k++)
if(get(k) instanceof Animal)
{
Animal a = (Animal)get(k);
score += a.livingCost;
}
return score;
}
public float animalWeight()
{
float weight = 0;
for(int k = 0; k < size(); k++)
if(get(k) instanceof Animal)
weight += get(k).w;
return weight;
}
public float plantWeight()
{
float weight = 0;
for(int k = 0; k < size(); k++)
if(get(k) instanceof Plant)
weight += get(k).w;
return weight;
}
protected void devide()
{
Dish d1 = new Dish(this);
Dish d2 = new Dish(this);
while(size() > 0)
{
Cell c = remove(size()-1);
if(random(1) > .5)
d1.add(c);
else
d2.add(c);
}
die();
dishes.add(d1);
dishes.add(d2);
}
public void killWorstDish()
{
int worst = 0;
for(int k = 1; k < dishes.size(); k++)
if(((Dish)dishes.get(k)).quality() < ((Dish)dishes.get(worst)).quality())
worst = k;
dishes.remove(worst);
}
public float dist(Dish d)
{
return loc.dist(d.loc);
}
public boolean touching(Dish d)
{
return loc.dist(d.loc) < 2*radius && d != this;
}
public String toString()
{
return " "+animalCostMod+" "+defMod+" "+visibility+" "+viscosity+" quality:"+quality();
}
private void die()
{
dishes.remove(this);
//radius = 0;
}
public void add(Cell c)
{
//c.myDish = this;
cells.add(c);
}
public Cell get(int index)
{
return (Cell)cells.get(index);
}
public Cell remove(Cell r)
{
int index = cells.indexOf(r);
if(index != -1)
return remove(index);
return null;
}
public Cell remove(int index)
{
return (Cell)cells.remove(index);
}
public int size()
{
return cells.size();
}
}
/**
Dhish, a simulation of evolution.
Green cells-plants, yellow-herbivores, red-carnivores.
Cells have many attributes some of which prove useful in getting food.
They pass these attributes on to their decedents, with some variation, thus the population evolves.
Mouse wheel to zoom. Click and drag to move dishes. Drag the edge of a dish to change its size.
P pauses. N makes a new dish. +/- changes the speed. Q toggles quality.
Double-click a dish to zoom in on it. Double-click an animal to control it. Your animal will follow the mouse.
Note: If you cant use the mouse wheel, right-click and drag instead.
Made by Rafael Cosman
*/
private float zoom;
public PVector center, mouse, cursor;
public final PVector ORIGIN = new PVector(0,0);
private Dish selected;
private boolean clickedRim;
private boolean paused;
private int frate;//frames per second
private boolean smoothed;
private int button;
public ArrayList dishes;
public final int numDishes = 1;
public boolean dishEvolution;
float radius;//the radiuses of the dishes
void mousePressed()
{
button = mouseEvent.getButton();
if(button == MouseEvent.BUTTON1)
{
selected = (Dish)dishes.get(0);
for(int k = 0; k < dishes.size(); k++)
{
Dish d = (Dish)dishes.get(k);
if(d.loc.dist(cursor) < selected.loc.dist(cursor))
selected = (Dish)dishes.get(k);
}
if(selected.loc.dist(cursor) > radius+5)
{
selected = null;
if(mouseEvent.getClickCount()==2)
addDish();
}
else if(mouseEvent.getClickCount()==2 && dishes.size() > 1)//double click
{
dishes = new ArrayList();
dishes.add(selected);
selected.loc = ORIGIN.get();//moveAll(PVector.mult(mouse,-1));
zoom(2);
dishEvolution = false;
}
else
clickedRim = abs(cursor.dist(selected.loc) - radius) < 10;
}
}
void mouseDragged()
{
PVector dmouse = new PVector(mouseX-pmouseX,mouseY-pmouseY);
dmouse.div(zoom);
if(selected != null)
{
if(clickedRim)//abs(cursor.dist(selected.loc) - selected.radius) < 10)
radius = selected.loc.dist(cursor);// - selected.loc.dist(new PVector(pmouseX,pmouseY)))/zoom;
else
selected.loc.add(dmouse);
}
else if(button == MouseEvent.BUTTON1)
moveAll(dmouse);
else if(true)//button == MouseEvent.BUTTON2 || button == MouseEvent.BUTTON3)
{
PVector pmouse = new PVector(pmouseX,pmouseY);
PVector pcursor = PVector.sub(pmouse,center);
pcursor.div(zoom);
zoom(pcursor.mag() / cursor.mag());
}
else
moveAll(dmouse);
}
void mouseReleased()
{
selected = null;
}
void keyPressed()
{
if(key == 'q')
{
smoothed = !smoothed;
if(smoothed)
smooth();
else
noSmooth();
}
else if(key == 'c')
{
Animal a = new Animal();
a.carn = 1;
a.maxSpeed *= 2;
((Dish)dishes.get(0)).add(a);
a.myDish = ((Dish)dishes.get(0));
}
else if(key == 'n')
{
addDish();
zoom(sqrt(dishes.size()-1) / sqrt(dishes.size()));
}
else if(key == 'r' && dishes.size() == 1)
((Dish)dishes.get(0)).add(new Rock());
else if(key == 'p')
{
paused = !paused;
if(paused)
frameRate(60);
else
frameRate(frate);
}
else if(key == 'd')
dishEvolution = !dishEvolution;
else if(key == '+' || key == '=')
frate *= 1.5;
else if(key == '-')
frate /= 1.5;
frate = max(frate,2);
frameRate(frate);
}
void setup()
{
colorMode(HSB,360);
frate = 18;
dishEvolution = false;
radius = 200;
size(800,650);
smoothed = true;
smooth();//makes the circles smoother, but slows down frame rate
center = new PVector(width/2, height/2);
zoom = 2;
paused = false;
cursor(CROSS);
dishes = new ArrayList();
for(int k = 0; k < numDishes; k++)
addDish();
/*
This listener thing is based off of
http://ingallian.design.uqam.ca/goo/P55/ImageExplorer/
*/
addMouseWheelListener(new java.awt.event.MouseWheelListener()
{
public void mouseWheelMoved(java.awt.event.MouseWheelEvent evt)
{
zoom(pow(.9,evt.getWheelRotation()));
}
}
);
}
void draw()
{
mouse = new PVector(mouseX,mouseY);
cursor = PVector.sub(mouse,center);
cursor.div(zoom);
if(dishes.size() == 0)
for(int k = 0; k < numDishes; k++)
addDish();
background(0);
translate(center);
scale(zoom);
//if(isolated != null)
//isolated.run();
//else
for(int k = 0; k < dishes.size(); k++)
{
pushMatrix();
Dish d = (Dish)dishes.get(k);
if(paused)
d.show();
else
{
d.run();
d.show();
}
popMatrix();
}
}
public void zoom(float factor)
{
/*
for(int k = 0; k < dishes.size(); k++)
{
Dish d = (Dish)dishes.get(k);
d.loc.sub(cursor);
}
center = mouse.get();//center.add(PVector.mult(cursor,zoom));
*/
zoom *= factor;
zoom = constrain(zoom, .01, 100);
}
public void moveAll(PVector move)
{
/*
for(int k = 0; k < dishes.size(); k++)
{
Dish d = (Dish)dishes.get(k);
d.loc.add(move);
}
*/
move.mult(zoom);
center.add(move);
}
//Draws a circle at point v, with width and height w.
public void ellipse(PVector v, float w)
{
//w *= 2;
ellipse(v.x,v.y,w,w);
}
public void ellipse(float w)
{
ellipse(ORIGIN,w);
}
public void translate(PVector v)
{
translate(v.x,v.y);
}
public void addDish()
{
dishes.add(new Dish(100,10));//,(int)random(3)));
}
class Plant extends Cell implements Runnable
{
public Plant()
{
super();
}
public Plant(Plant parent)
{
super(parent);
}
/*
public Plant(Plant m, Plant d)
{
super(m,d);
calcCost();
}
*/
public void run()
{
if(loc.dist(ORIGIN) + w/2 > radius)
die();
w += myDish.sunlight * w / 30;
myColor = color(130,360,260*w/maxSize);
super.run();
}
}
class Rock extends Cell implements Runnable
{
public Rock()
{
super();
myColor = (int)random(80);
w = 200;
loc = cursor.get();//loc.mult(1.5);
}
public void run()
{
push();
loc.limit(radius);
}
public void show()
{
super.show();
pushMatrix();
translate(loc);
colorMode(HSB,360);
stroke(200);
strokeWeight(def/2);
fill(myColor);
ellipse(sqrt(w)*2);
popMatrix();
}
public void mouseOver()
{
}
}