Project 1: TextRain

screenshot

Here is my reimplementation of TextRain. I am offering more of a proof of concept solution, so I could really keep things simple. The implementation process is the following: reading a text file with famous quotes on every line, at start initializing an ArrayList of all the letters from every loaded text line, positioned regarding their order in the sentence. Then on every frame I get a live video feed from my webcam and going through all “flying” letters, I check if they collide with these areas of the image that are darker then my “collisionThreshold”, if they collide, I keep the letter still, if not the letter continues down the road.

Code: https://github.com/kamend/IACD_TextRain

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import processing.video.*;
 
// objects
class Letter {
  PVector vel;
  PVector pos; 
  char ch;
  color col;
};
 
// global vars
int videoWidth = 640;
int videoHeight = 480;
Capture cap; // video capture device
 
ArrayList(Letter) LetterList = new ArrayList(Letter)(); // the list that will hold the particles
 
float letterXOffset = 10; // how far we should draw the individual letters
float letterYOffset = 400; // how far every sentence should be
float collisionThreshold = 30; // haw dark the areas of collision must be
PFont font;
 
void setup() {
  size(640, 480);
 
  // initalizes video capture
  cap = new Capture(this, videoWidth, videoHeight);
  cap.start();
 
  // read text and launch "particles"
  launchSentences();
 
  // setup display font
  font = createFont("Helvetica Bold", 16, true);
  textFont(font, 16);
}
 
void launchSentences() {
 
  // read sentences from a file
  String lines[] = loadStrings("text.txt");
 
  for (int lineNum = 0;lineNum < lines.length;lineNum++) {
    String sentence = lines[lineNum];
    int setanceLength = sentence.length();
    for (int i=0;i<setanceLength;i++) {
      char character = sentence.charAt(i);
      if (character == ' ') continue;
      Letter l = new Letter();
      l.ch = character;
      l.pos = new PVector(letterXOffset * i, -lineNum * letterYOffset-letterYOffset/4, 0.0);
      l.vel = new PVector(0.0, 0.5 + random(0, 0.1), 0.0);
      l.col = color(255, 255, 255);
      LetterList.add(l);
    }
  }
}
 
void update() {
  // read video feed
  if (cap.available()) {
    cap.read(); 
    cap.loadPixels();
  }
 
  for (int i=0;i<LetterList.size();i++) {
    Letter l = LetterList.get(i);
    // if the letter is not colliding continue down
    if (!isColliding(l.pos))
      l.pos.add(l.vel);
 
    // if we reach the bottom, go at the top again
    if (l.pos.y > height) {
      l.pos.y -= height+letterYOffset;
    }
  }
}
 
boolean isColliding(PVector pos) {
  float radius = 10.0;
  if (pos.y > radius && pos.y < = videoHeight-radius && pos.x >=0 && pos.x < videoWidth) {
    PVector pixelPos = pos.get();
    pixelPos.add(0.0, radius, 0.0);
    int pixelIndex = floor(pixelPos.x) + floor(pixelPos.y)*videoWidth;
    color pixelColor = cap.pixels[pixelIndex];
 
    if (brightness(pixelColor) < collisionThreshold)
      return true;
  }
  return false;
}
 
void draw() {
  update();
 
  background(0);
  image(cap, 0, 0); 
 
  for (int i=0;i<LetterList.size();i++) {
    Letter l = LetterList.get(i);
    if (l.pos.y >= 0.0) {
      fill(l.col, 255 - abs(map(l.pos.y, 0, height, -200, 200)));
      text(l.ch, l.pos.x, l.pos.y);
    }
  }
}