previous sketch Fox and Hen next sketch

Click and drag the white dot!

In this idealized farm, you control the hen, drawn as a white circle. You're chased by a fox, shown as a brown circle. The fox doesn't want to eat you, it just wants to be nearby. But it doesn't want to scare you, so as it gets closer to you it slows down. For fun, I change the size of the fox based on how fast it's moving.

Try turning the hen on and off, and try moving your mouse in different ways. For example, while holding down the mouse button, keep the mouse still for a moment, make one quick move, then stop again. Try repeating this to get some cool patterns!

You can control this interaction using the keyboard:

  • a   make the fox move a little slower
  • d   make the fox move a little faster
  • b   toggle the drawing of trails. Turning off trails clears the farmyard.
  • f   toggle drawing of the fox
  • h   toggle drawing of the hen
  • r   toggle the change in the fox's size

The Program

float FoxX, FoxY, FoxR;          // the fox's center and radius
float HenX, HenY, HenR;          // the hen's center and radius
color FoxColor, HenColor;        // animal colors
boolean FoxVisible, HenVisible;  // are we drawing these?
float FoxSpeed;                  // the fox's speed, from 0 to 1
color BGcolor;                   // the background color
boolean ClearBG;                 // clear the background on each frame?
boolean ScaleRadius;             // scale the fox's radius with distance?

void setup() {
  size(600, 500);                // make a window 600 wide by 500 high
  smooth();                      // and draw everything pretty
  // set starting values for the global variables
  BGcolor = color(20, 95, 50);   // background color
  FoxX = width/2.0;              // the fox's starting position
  FoxY = height/2.0;
  FoxR = 10;                     // radius of the fox's circle
  FoxColor = color(180, 120, 50);  // a brown-ish fox
  HenX = width/2.0;              // the hen's starting position
  HenY = height/2.0;
  HenR = 20;                     // the hen's radius
  HenColor = color(210, 210, 195);   // a white-ish hen
  ClearBG = false;               // don't clear background on each frame
  ScaleRadius = true;            // fox changes size with speed
  FoxVisible = true;             // draw the fox
  HenVisible = true;             // draw the hen
  
  FoxSpeed = .08;                // fox's speed: bigger = faster
  background(BGcolor);
}

void draw() {
  if (ClearBG) background(BGcolor);
  
  /* Move the fox.  We move the fox some percentage of the way 
  from its current location to the hen's location, based on
  the value of FoxSpeed.  */
  FoxX = lerp(FoxX, HenX, FoxSpeed);
  FoxY = lerp(FoxY, HenY, FoxSpeed);
  
  float foxR = FoxR;
  if (ScaleRadius) {  // should we scale the fox's size?
    float d = dist(HenX, HenY, FoxX, FoxY);
    foxR = map(d, 0, 100, 1, 3*FoxR);
  }
  
  // draw everything
  fill(HenColor);
  if (HenVisible) ellipse(HenX, HenY, 2*HenR, 2*HenR);
  fill(FoxColor);
  if (FoxVisible) ellipse(FoxX, FoxY, 2*foxR, 2*foxR);
}

void mousePressed() { setHenToMouse(); }
void mouseDragged() { setHenToMouse(); }

void setHenToMouse() {  // the hen moves with the mouse
  HenX = mouseX;
  HenY = mouseY;
}

void keyTyped() {
  if (key == 'a') FoxSpeed -= .01;            // slow down the fox
  if (key == 'd') FoxSpeed += .01;            // speed up the fox
  if (FoxSpeed < 0) FoxSpeed = 0;             // don't allow speed to be negative
  if (key == 'b') ClearBG = !ClearBG;         // toggle clearing the background
  if (key == 'f') FoxVisible = !FoxVisible;   // toggle drawing the fox
  if (key == 'h') HenVisible = !HenVisible;   // toggle drawing the hen
  if (key == 'r') ScaleRadius = !ScaleRadius; // toggle scaling the fox's size
}