Generative Text: Net

For this assignment, we were asked to create a generative text or data visualization piece. I’m interested in both, but I especially wanted to experiment with text. In the beginning, I wanted to create some form of a playful horoscope generator but the structuring of words, their sentence placement, and concepts such as context-free grammar were a little bit too difficult to understand.

Instead, I created a piece where there is a “net” of letters, and you have to click on the sketch to generate the word “net”.  In the beginning, I thought of adding a scoreboard and turning it into a game where every time you generate the word, you earn a point–– but apart from the fact that it’s tricky, I realized it would defy the purpose of the sketch being a simple play on words where the user interaction is somewhat open-ended.

You can also refresh the letters by pressing the spacebar, the first press removes all the letters and the second press will rearrange them.

Here is the end result (I updated the video):

And here is an Arabic version:

And here is the code:

//Source: textArrayClass3-Bounce by Taylor Hedum on OpenProcessing


String[] character = {"N", "T", "E", "N", "T", 
"E", "T", "T", "T", "N", "E", "T", "N", "E", "T", "N", 
 "E", "T", "N", "T", "E"};
//  //"E", "B", "E", "E", "B"
//String[] character = {"N", "E", "T"};
//String[] character = {"ش", "ب", "ك", "ة", "ش", "ب", "ك", "ة", "ش", "ب", "ك", "ة", "ش", "ب", "ك", "ة"};
int tSize = 36;

ArrayList<Chara> charas = new ArrayList<Chara>();
int charaLim = character.length;
//int charaLim = 50;
int randoChara;

float spring = 0.3;
float gravity = 0.1;
float friction = -0.9;
int charaCounter;
boolean showLetters = true;


//PImage bg;

void setup() {
  size(500,500);
  textSize(tSize);
  textAlign(CENTER);
  //frameRate(4);
  
  for (int i=1; i<charaLim+1; i++) {
    
    //used to generate random character in character array
    randoChara = int(random(0, character.length));
    //bg = loadImage("8.png"); 
    
    //add all characters in character array to list of characters to get initial bouncing going
    charas.add(new Chara(i, randoChara, width/(charaLim+1)*i, random(height/2), tSize));
  }
}

void draw() {
   background(220,220,220);
  for (int i = 0; i < charas.size(); i++) {
    Chara chara = charas.get(i);
    chara.collide();
    chara.move();
    chara.display();
  }
  if (mousePressed) {
    //addOne();
  }
  for (int i = charas.size(); i > 0; i--) {
    
    //starts deleting characters when the set limit of characters is reached
    //deletes character at the beginning of list, the oldest character so to speak
    if (charas.size() > charaLim*2) {
      deleteOne(1);
    }
  }

}

void mousePressed() {
  addOne();
}

//adds new character upon mousePress
void addOne() {
  randoChara = int(random(0, character.length));
  
  //passes MouseX & MouseY to class constructor so that character is first drawn where the mouse is
  charas.add(new Chara(charas.size()+1, randoChara, mouseX, mouseY, tSize));
}


void deleteOne(int delid) {
  
  //removes first character in arrayList since delid is always passed as 1
  charas.remove(delid-1);
  
  //moves up the other character's IDs by one
  for (int i = delid-1; i<charas.size(); i++) {
    Chara chara = charas.get(i);
    chara.reOrder();

  }
}

void keyPressed(){
  if (key == ' '){
    showLetters = !showLetters;
  }
}

class Chara {
  int id;
  int whichChara;
  float x, y;
  float diameter;
  float vx = 0;
  float vy = 0;
  float xx = random (0, 500);
  float xS;
  int offSet = 250;
  float r;
  float rd = 1;

  Chara(int idint, int randoChara, float xin, float yin, float din) {
    id = idint; 
    whichChara = randoChara;
    x = xin;
    y = yin;
    diameter = din;
    r = random(width/4, width/2);
  }

  void collide() {
    for (int i = 0; i < charas.size(); i++) {
      Chara others = charas.get(i);
      if (others != this) {
   
       
        float dx = others.x - x;
        float dy = others.y - y;
        
        //pythogonal distance
        float distance = sqrt(dx*dx + dy*dy);
        
        //draws line between characters if they're close enough
        float minDist = others.diameter/4 + diameter/4;
        if (distance < minDist*8) { 
          line(x, y, others.x, others.y);
        }
        
        //makes characters bounce of each other if they come within minDist of each other
        if (distance < minDist) { 
          float angle = atan2(dy, dx); //angle determined by atan2 and distance between characters
          float targetX = x + cos(angle) * minDist;
          float targetY = y + sin(angle) * minDist;
          
          //acceleration 
          float ax = (targetX - others.x) * spring;
          float ay = (targetY - others.y) * spring;
          vx -= ax;
          vy -= ay;
          others.vx += ax;
          others.vy += ay;

        }
      } else {
        fill(0);
      }
    }
  } 
  
  void move() {
    vy += gravity;
    x += vx;
    y += vy;
    
    //if character hits/goes past right sides of the canvas,
    //reset x so it seems to bounce off the edge of canvas,
    //then change direction of x-movement
    if (x + diameter/2 > width) {
      x = width - diameter/2;
      vx *= friction;
      
    //likewise but for left side of canvas
    } else if (x - diameter/2 < 0) {
      x = diameter/2;
      vx *= friction;
    } //likewise but for height
    if (y + diameter/2 > height) {
      y = height - diameter/2;
      vy *= friction;
    } else if (y - diameter/2 < 0) {
      y = diameter/2;
      vy *= friction;
    }
  } 

  void display() {
  fill(0);
  
    //if showLetters is true (toggled by space bar), draw the letter
    if (showLetters) {
      text(character[int(whichChara)], x, y+diameter/3);
    }

    stroke(135,206,235);
    strokeWeight(1);

  }
  void reOrder() {
    id-=1;
  }
}

 

Leave a Reply