Speech Bubbles Code

From CSclasswiki
Jump to: navigation, search

April 28th Program Code

The following is the final "Speech Bubbles" program in full, written using Processing. This program includes code for panels using images, as well as code for panels as colors (these parts have been commented out).

int panel = 205; // square panel dimension

void setup(){
  //randomSeed(1);
  int w = 3 * panel; //width of the window is the width of 3 panels
  int panelNum = int(random(1,9)); //Choose a number to decide how many panels there will be
  int h = (1 + ((panelNum-1) / 3)) * panel; //Height of the window
  println("panelNum=" + panelNum + " w,h=" + w + " " + h);
  size(w,h);  //create the window
  
  int nimages = 23; //use this number for the maximum in "howMany"; basically how many images are in the array
  int nimagesBG = 7;
  int nimagesBG2 = 1;
  
  
  background(255);
  // Fill up color array.  9 colors for now. Use color() to create color types.
  color Color[] = {
    color(252,59,59), //red
    color(175,5,5), //red
    color(255,182,126), //orange
    color(247,230,35), //yellow
    color(255,237,131), //yellow
    color(198,237,101), //green
    color(191,242,149), //green
    color(119,240,186), //blue
    color(9,222,220), //blue
    color(74,100,237), //blue
    color(175,234,229), //blue
    color(161,133,232), //purple
    color(222,154,212), //purple
    color(242,22,125), //pink
    color(245,168,192),
    color(250,248,235) //white
  };
  
  // images
  PImage[] speechBubbles = new PImage[30];
    speechBubbles[0] = loadImage("bubble1.gif");
    speechBubbles[1] = loadImage("bubble2.gif");
    speechBubbles[2] = loadImage("bubble3.gif");
    speechBubbles[3] = loadImage("bubble4.gif");
    speechBubbles[4] = loadImage("bubble5.gif");
    speechBubbles[5] = loadImage("bubble6.gif");
    speechBubbles[6] = loadImage("bubble7.gif");
    speechBubbles[7] = loadImage("bubble8.gif");
    speechBubbles[8] = loadImage("bubble9.gif");
    speechBubbles[9] = loadImage("bubble10.gif");
    speechBubbles[10] = loadImage("bubble11.gif");
    speechBubbles[11] = loadImage("bubble12.gif");
    speechBubbles[12] = loadImage("bubble13.gif");
    speechBubbles[13] = loadImage("bubble15.gif");
    speechBubbles[14] = loadImage("bubble16.gif");
    speechBubbles[15] = loadImage("bubble17.gif");
    speechBubbles[16] = loadImage("bubble18.gif");
    speechBubbles[17] = loadImage("bubble19.gif");
    speechBubbles[18] = loadImage("bubble20.gif");
    speechBubbles[19] = loadImage("bubble21.gif");
    speechBubbles[20] = loadImage("bubble22.gif");
    speechBubbles[21] = loadImage("bubble23.gif");
    speechBubbles[22] = loadImage("bubble24.gif");
    speechBubbles[23] = loadImage("bubble25.gif");

  PImage[] bgPics = new PImage[10];
    bgPics[0] = loadImage("comic1.jpg");
    bgPics[1] = loadImage("comic2.jpg");
    bgPics[2] = loadImage("comic3.jpg");
    bgPics[3] = loadImage("comic4.jpg");
    bgPics[4] = loadImage("comic5.jpg");
    bgPics[5] = loadImage("comic6.jpg");
    bgPics[6] = loadImage("comic7.jpg");
    bgPics[7] = loadImage("comic8.jpg");
  
  PImage[] bgPicsWide = new PImage[3];
    bgPicsWide[0] = loadImage("comiclong1.jpg");
    bgPicsWide[1] = loadImage("comiclong2.jpg");
  
  int Case = (panelNum % 3);
  // Case 1 means 1 panel in last row
  // Case 2 means 2 panels
  // Case 0 means last row is filled.
  println("Case = " + Case ); 
 
  // i runs over the # of panels
  for( int i=0; i < panelNum; i++ ) {
    // row is i / 3 discarding remainder, which is what int / does.
    // col is the remainder, which is what the % operator.
    int row = i / 3;
    int col = i % 3;
    println("**** PANEL NUMBER i=" + i + " row=" + row + " col=" + col);
    if ( panelNum / 3 == row ) { // if you're on the last row...
      print("Last row");
      if ( Case == 0 ) { //...and the last row is filled with three panels...
        println(" Case0"); 
        squareCase(speechBubbles, bgPics, nimages, nimagesBG, col*panel, row*panel, panel, panel);
        //PaintPanel(speechBubbles, nimages, col * panel, row * panel, panel, panel, Color[int(random(0,15))]);
      } 
      if ( Case == 1 ) { //...but if there's 1 panel...
        println(" Case1");
        otherCase(speechBubbles, bgPicsWide, nimages, nimagesBG2, col*panel, row*panel, 3*panel, panel);
        //PaintPanel(speechBubbles, nimages, col * panel, row * panel, 3*panel, panel, Color[int(random(0,15))]);
      }
      if ( Case == 2 ){
        println(" Case2");
        int randWidth = int(random(90,width-90));
        int secondWidth = (width - (randWidth));
        println("randWidth=" + randWidth + " secondWidth=" + secondWidth);
        otherCase(speechBubbles, bgPicsWide, nimages, nimagesBG2, col*panel, row*panel, randWidth, panel);
        //PaintPanel(speechBubbles, nimages, col * panel, row * panel, randWidth, panel, Color[int(random(0,15))]);
        noTint();
        fill(255);
        noStroke();
        rect((randWidth - 4), (row *panel), (secondWidth + 5), panel);
        noFill();
        otherCase(speechBubbles, bgPicsWide, nimages, nimagesBG2, randWidth, row*panel, secondWidth, panel);
        //PaintPanel(speechBubbles, nimages, randWidth, row * panel, secondWidth, panel, Color[int(random(0,15))]);
        i = panelNum; // to force loop to end?
      }
      
    }
    else
      squareCase(speechBubbles, bgPics, nimages, nimagesBG, col*panel, row*panel, panel, panel);
      //PaintPanel(speechBubbles, nimages, col * panel, row * panel, panel, panel, Color[int(random(0,15))]);
  }
}

// Paint a panel starting at upperleft corner x,y, in color c.
/*
void PaintPanel(PImage[] speechBubbles, int nimages, int x, int y, int wpanel, int panel, color c) {
  fill( c );
  noStroke();
  println("wpanel=" + wpanel);
  rect((x+5), (y+5), (wpanel-5), (panel-5));
  int repeatNum = int(random(0,4));
  
  drawBubble(speechBubbles, nimages, x, y, wpanel, panel);
  
}
*/

void squareCase(PImage[] speechBubbles, PImage[] bgPics, int nimages, int nimagesBG, int x, int y, int wpanel, int panel){
  int whatBG = int(random(0,nimagesBG));
  tint(255,200);
  image(bgPics[whatBG],(x+5),(y+5));
  noTint();
  drawBubble(speechBubbles,nimages,x,y,wpanel,panel);
}

void otherCase(PImage[] speechBubbles, PImage[] bgPicsWide, int nimages, int nimagesBG2, int x, int y, int wpanel, int panel){
  int whatBG2 = int(random(0,nimagesBG2));
  tint(255,200);
  image(bgPicsWide[whatBG2],(x+5),(y+5));
  noTint();
  drawBubble(speechBubbles,nimages,x,y,wpanel,panel);
}

void drawBubble(PImage[] speechBubbles, int nimages, int xpanel, int ypanel, int wpanel, int hpanel){
  int threshold = 30; // percent
  int nmax = 30;  //set a size for the following arrays (doesn't really matter what the size is)
  int imageXs[] = new int[nmax];
  int imageYs[] = new int[nmax];
  int imageWidths[] = new int[nmax];
  int imageHeights[] = new int[nmax];
    
  int howMany = int(random(1,3));  //Draw how many images?
  println("howMany=" + howMany);
  
  for(int i = 0; i < howMany; i++){  //For loop for drawing images; depends on "howMany"
  
    int rimage = int(random(0,nimages));  //Pick an index in the array of images
    println("rimage=" + rimage);
   
    PImage thisImage = speechBubbles[rimage];   //The random-index image turned into a variable
     
    imageWidths[i]  = thisImage.width; 
    imageHeights[i] = thisImage.height;
    
    boolean finished = false;
    // block infinite loop eventually
    int count = 0;
    int countmax = 10;
    float s1 = 0.6;
    float s2 = 0.25;
    while (!finished && count < countmax) {
      
      int xpoint = int(random(xpanel, xpanel + s1*wpanel));  //Choose x
      imageXs[i] = xpoint; //Append x to the list
      // Note: wpanel and hpanel need to be scaled to eliminate too much run-off
      int ypoint = int(random(ypanel, ypanel + s2 * hpanel)); //Choose y
      imageYs[i] =  ypoint; //Append y to the list
        
      boolean toomuchOverlap = false;
      for( int j=0; j < i; j++ ) {
        // check to see if the images overlap
        int percent = PercentOverlap(imageXs[j], imageYs[j], imageWidths[j], imageHeights[j], imageXs[i], imageYs[i], imageWidths[i], imageHeights[i]);
        if (percent > threshold) {
          toomuchOverlap = true;
          break;
        } 
      }//for
      if (toomuchOverlap) {
        finished = false;
      }
      else {
        finished=true;
      }
      count++;
      println("While Count =" +count);
      if ( count >= countmax ) {
        println("Error DrawBubble: could not place image");
     
      }
    } //while loop
    
    drawImage(thisImage, imageXs[i], imageYs[i]);  //Draw the image!
   
  }
  PrintIntArray( "imageXs", imageXs, howMany );
  PrintIntArray( "imageYs", imageYs, howMany );
  PrintIntArray( "imageWidths", imageWidths, howMany );
  PrintIntArray( "imageHeights", imageHeights, howMany );
  
  }
//} // I ADDED THIS BECAUSE I THOUGHT IT WAS THE PROBLEM

void PrintIntArray( String name, int array[], int n ) {
  println("Printing array " + name);
  for ( int i =0; i < n; i++ ) {
    println("i=" + i + " array[i]=" + array[i] );
  }
}
    

void drawImage(PImage imgName, int xpoint, int ypoint){
    smooth();
    image(imgName, xpoint, ypoint);
  }
  
int PercentOverlap(int x1, int y1, int w1, int h1, int x2, int y2, int w2, int h2){
  // find the area overlap in pixels
  int area = RectangleIntersection(x1, y1, w1, h1, x2, y2, w2, h2);
  println("PercentOverlap: area="+area);
  // convert to a percentage of the area of the smaller of the two
  int areasmaller = min( w1 * h1, w2 * h2 );
  int percent = int(100 * float(area) / float(areasmaller));
  println("PercentOverlap (w.r.t smaller)="+percent);
  return percent;
}

// The 8 args to this function are the four ints that determine each rectangle,
// in the same order as in the rect() function: x,y,w,h.
// Returns overlap in pixels (not percentage!)
int RectangleIntersection(int x1, int y1, int w1, int h1, int x2, int y2, int w2, int h2) {
  int xoverlap = Overlap1D(x1, x1+w1, x2, x2+w2);
  if (xoverlap == 0) { 
    println("No xoverlap");
    return 0; 
  }
  int yoverlap = Overlap1D(y1, y1+h1, y2, y2+h2);
  if (yoverlap == 0) { 
    println("No yoverlap");
    return 0; 
  }
  println("xoverlap="+xoverlap+" yoveralp="+yoverlap);
  return xoverlap * yoverlap;
}

// This function computes overlap in one dimension, i.e., of segments.
// Returns an integer.
int Overlap1D(int x1, int x2, int x3, int x4) {
  if (x4 <= x1) { return 0;}
  if (x2 <= x3) { return 0;}
  // they overlap
  int overlap = -1; // as a default; should never be returned
  // first check for total overlap
  if      ((x3 <= x1) && (x2 <= x4)) { overlap = x2-x1; }
  else if ((x1 <= x3) && (x4 <= x2)) { overlap = x4-x3; }
  // now partial overlaps
  else if ((x3 <= x1) && (x1 <= x4)) { overlap = x4-x1; }
  else if ((x3 <= x2) && (x2 <= x4)) { overlap = x2-x3; }
  else if ((x1 <= x3) && (x3 <= x2)) { overlap = x2-x3; }
  else if ((x1 <= x4) && (x4 <= x2)) { overlap = x4-x2; }
  else println("Error in Overlap1D!");
  
  return overlap;
}