Text Rain: Processing Implementation

Author: Marlena Summary: A reimplementation of Text Rain using Processing Abstract: This is Part B of the Project-1 Upkit Intensive. It is a reimplementation of Camille Utterback and Romy Achituv's 1999 project by the same name. Repository: https://github.com/thisisanexparrot/Text_Rain_Processing_Assign

I decided to take an object oriented approach to my solution. Given an input string, the program splits the string into individual letters. Each letter is made into its own object and stored in an array of these Letter objects. This process is repeated to create several lines of the string that are then staggered at their start positions to create the “raining” effect.

From there, the program is loops continuously over every Letter object and checks the brightness of the pixel directly below it. If the brightness meets a certain threshold the letter will be pushed up until it finds a pixel of the correct threshold. This makes it appear as though the letters are floating on the darker areas of the screen. Otherwise, the letters fall to the bottom of the screen where they fade and are reset to above the top of the screen.

The code for this program is available on the included Github link and is also copied below:

int sWidth = 1200;
int sHeight = 800;
int threshold = 140;
String inputString = "Rain, rain, go away; come again some other day.";
char[] inputLetters;
int dupStrings = 10;

void setup() {
  String[] cameras = Capture.list();

  drops = new Letter[dupStrings][inputString.length()];
  int inc = sWidth/inputString.length();
  int spawnPos = 5;
  inputLetters = new char[inputString.length()];
  splitString();

  int addLineHeight = 0;
  for (int i = 0; i < dupStrings; i++) {
    for (int j = 0; j < inputLetters.length; j++) {
      Letter testLetter = new Letter(inputLetters[j]);
      testLetter.xpos = spawnPos;
      testLetter.ypos -= addLineHeight; 
      drops[i][j] = testLetter;
      spawnPos += inc;
      if (spawnPos >= sWidth-inc) {
        spawnPos = 5; 
      }
    }
    addLineHeight += 50;
  }
 
  if (cameras.length == 0) {
    println("There are no cameras available...");
    size(400, 400);
    exit();
  }
  else {  
    println("Availaable cameras:");
    for (int i = 0; i < cameras.length; i++) {
      println(cameras[i]);
    }
    cam = new Capture(this, sWidth, sHeight);
    cam.start();
    cam.loadPixels();

    size(sWidth, sHeight);
  }
  dropsLength = inputString.length();
}

void splitString() {
  for (int i = 0; i < inputString.length(); i++) {
    inputLetters[i] = inputString.charAt(i); 
  } 
}

void draw() {
  if (cam.available() == true) {
    cam.read();
  }
  set(0, 0, cam);
  for (int i = 0; i < dupStrings; i++) {
    for (int j = 0; j < dropsLength; j++) {
      if (drops[i][j].ypos < sHeight && drops[i][j].ypos > 0) {
        int loc = drops[i][j].xpos + (drops[i][j].ypos*sWidth);
        float bright = brightness(cam.pixels[loc]);
        if (bright > threshold) {
          drops[i][j].dropLetter();
          drops[i][j].upSpeed = 1;
        }
        else {
          if (drops[i][j].ypos > 0) {
            int aboveLoc = loc = drops[i][j].xpos + ((drops[i][j].ypos)-1)*sWidth;
            float aboveBright = brightness(cam.pixels[aboveLoc]);
            if (aboveBright < threshold) {
              drops[i][j].liftLetter();
              drops[i][j].upSpeed = drops[i][j].upSpeed * 2;
            }
          }
        }
      }
       else {
        drops[i][j].dropLetter();
      }

      drops[i][j].drawLetter();
      cam.updatePixels(); 
    }
  }
}

class Letter {
  int xpos;
  int ypos;
  char textLetter;
  int upSpeed;
  int alpha = 255;
  Letter(char inputText) {
    xpos = 100;
    ypos = int(random(-1050, 0));
    textLetter = inputText;
    textSize(16);
    upSpeed = 1;
  }
  void drawLetter() {
    fill(166, 020, 020, alpha);
    text(textLetter, xpos, ypos);
  }

  void letterFade() {
    alpha -= 5;
    if(alpha <= 0) {
      ypos = int(random(-350, 0));
      alpha = 255;
    }
  }

  void dropLetter() {
    ypos++;
    if (ypos > 730) {
      letterFade();
    }
  }

  void liftLetter() {
    int newY = ypos - upSpeed;
    if (newY >= 0) {
      ypos = newY;
    } 
    else {
      ypos = 0;
    }
  }
}


This entry was posted in project-1, text-rain on by .

About Marlena

Marlena Abraham is a sophomore officially studying computer science and unofficially studying biking, mechanical engineering, design, cooking, board games, knitting, traveling, hacking toy cars, RPG's, and creative expressions of all kinds. She likes to pick up new skills wherever she can find them and likes even more to find the opportunities to apply them.

Leave a Reply