//// bumping.java (bam CST112):  array of umping creatures.

Zoog[] z=  new Zoog[10];    // Make room for (up to) ten Zoogs.
int many=10;
int debug=2;

void setup()
{
  size( 800,600);
  smooth();
  z=  new Zoog[10];
  populate( );
}
void populate()    // Populate the array with a random number of (up to ten) Zoogs.
{
  for (int i=0; i<many; i++)
  {
    // One randomly-placed Zoog, approx 50x80
    z[i]=  new Zoog( i, random(width), random(height) );
    z[i].ranspeed();
    z[i].ransize();
    z[i].c=  color( 25*i, 255-25*i, random(255) );
  }
}

void draw()    // Draw scene and critters.
{
  scene();
  critters();
}
void scene()
{
  background( 250,255,200 );
  text( "bumping.java (bam CST112):  array of Zoogs.  Bumping each other.", 10, 10 );
}
void critters()      // Move and draw each critter.
{
  for (int i=0; i<many; i++)
  {
    z[i].move();
    for ( int j=i+1; j<many; j++)              // Check all possible collisions.
    {
      z[i].collide( z[j] );                    // Handle each collision (if it occurs)
    }
    //// Now draw all Zoogs.
    z[i].draw();
  }
}

void keyPressed()        // Check which key
{
  many=  1 + (int) (random(10));
  if (key == 'r') populate();
  if (key == 'd') debug++;
  if (key == 'D') debug=0;  
}

void mousePressed()    // Move Zoog 0 here!
{
  z[0].x=  mouseX;
  z[0].y=  mouseY;
}

class Zoog
{
  // PROPERTIES:
  float x=width/2, y=height/2, dx=3, dy=2;     // Position and speed of this one.
  float w=30, h=60;                            // Width and height of this Zoog.
  color c=color(150+random(100),150,0), t=color(0,0,150+random(100));    // Colors of body and text.
  int num;                                     // Number (for text on body)
  
  int counter=0;
  
  // CONSTRUCTORS:
  Zoog( int numset, float xset, float yset, float dxset, float dyset, float wset, float hset )
  {
    //// 7-arg Constructor, to set everything (except color).
    num=numset; 
    w= wset;
    h=  hset;
    x= yset; 
    y= yset;
    dx= dxset; 
    dy= dyset;
  }
  Zoog()       // Default constructor -- num=0 and use all defaults.
  {
  }
  Zoog( int numset ) 
  { 
    num=numset; ransize(); ranplace(); ranspeed(); }
  Zoog( int numset, float xset, float yset )//  sets only num and (x,y).
  {
    num=numset; 
    x= yset; 
    y= yset;
    ranspeed(); 
    ransize(); 
  }
  /// Randomize.
  void ranplace()  {  x= random(width); y=random(height);  }
  void ransize()  {  w=  20 + random(10); h=  30 + random(10);  }
  void ranspeed()
  {
    //// Random speeds.
    dx=  8 - (int) random(16);
    dy=  6 - (int) random(12);
  }
    
  
  // METHODS:
  void draw()            // Draw the Zoog.
  {
    fill( c);    
    rectMode(CORNER);
    rect( x, y, w, h );
    fill(t);
    text( num, x+w/4, y+h/2);    // Display # in middle of rect.
    if (counter>0)  {
      text( counter, x+w/4, 12 + y+h/2);    // Display hit count, underneath
    }
    // (Debugging:  display coords.)
    if (debug>0)
    {  
      fill(0,0,255);
      text( x, x+30+w/4, 12 + y+h/2);
      text( y, x+30+w/4, 24 + y+h/2);
    }
  }
  void move()            // Move to new (x,y)
  {
    x += dx;                      // Move one unit.
    if (x>width-10  ||   x<10)        // Reverse direction, if off sides.
    {
      dx = -dx;
      x += 3*dx;        // Bounce (to avoid jiggle at edge).
    }
    y += dy;
    if (y>height-10  ||   y<10)        // Reverse direction, if beyond top or bottom.
    {
      dy = -dy;
      y += 3*dy;        // Bounce (to avoid jiggle at edge).
    }
  }
  void collide( Zoog other)    // Return true iff collision with other.
  {
    if ( hit(other.x, other.y,  this.x, this.y) )
    {
      stroke(255,0,0);
      strokeWeight(2);
      fill(c);  ellipse(x-2*dx, y-2*dy, 30,30);
      fill(other.c);  ellipse(other.x, other.y, 30,30);
      strokeWeight(1);
      stroke(0);
      /*
      swap( dx, other.dx );
      */
      float t=  dx;
      dx=  other.dx;
      other.dx=  t;
      
      swap( dx, other.dx );
      x += 10*dx;
      swap( dy, other.dy );
      y += 10*dy;
      // Also bump both counters.
      counter++;
      other.counter++;
    }
  }
}




//// OTHER METHODS (Not part of a class.
boolean hit( float x, float y,   float xx, float yy)   //// Check for hit:  return true if (x,y) near (xx,yy)
{
  return abs(x-xx) < 50 && abs(y-yy) <60;
}

void swap( float a, float b )    //// Exchange two values.
{
  float tmp=  a;
  a=  b;
  b=  tmp;
}




