To implement text rain I created a class called Letter which contains a position, velocity, char, and some functions to move the letter and check if it is sitting on dark pixels. To move the letters up I check another pixel above the first, and if it is also dark enough, the letter moves up to that position. After changing the video to grey scale I simply check the red values (r,g, and b are now all the same) and if they are below a threshold, which i determined experimentally, they cause the letter to stop moving downward, or even move upward.
https://github.com/jlopezbi/textRainImplementation
import processing.video.*;
Capture video;
int[] backgroundPixels;
int numPixels;
int numLetters = 300;
float threshold = 31;
ArrayList rain;
void setup() {
size(600, 450, P2D);
smooth();
video = new Capture(this, 160, 120);
video.start();
numPixels = video.width * video.height;
backgroundPixels = new int[numPixels];
loadPixels();
rain = new ArrayList();
for (int i = 0; i< numLetters;i++) {
genRandLtr();
}
}
void draw() {
if (video.available()) {
video.read();
video.filter(GRAY);
image(video, 0, 0, width, height);
}
loadPixels();
for (int i =0;i<rain.size()-1;i++) {
Letter l = (Letter) rain.get(i);
l.updatePos();
l.display();
if (l.finished()) {
rain.remove(i);
genRandLtr();
}
}
color pix = pixels[mouseY*width+mouseX];
println(red(pix) +" "+ green(pix)+" "+ blue(pix));
updatePixels();
}
void genRandLtr() {
PVector pos = new PVector(random(0, width), 30);
PVector vel = new PVector(0, random(0.5, 1));
int lowerUpper = (int)random(2);
int ascii;
if (lowerUpper == 0) {
ascii = (int) random(65, 90.1);
}
else {
ascii = (int) random(97, 122.1);
}
char ltr = char(ascii);
Letter letter = new Letter(pos, vel, ltr);
rain.add(letter);
}
class Letter {
//GLOBAL VARIABLES
PVector pos;
PVector vel;
char ltr;
int aboveCheck = 4;
//CONTRUCTOR
Letter(PVector _pos, PVector _vel, char _ltr){
pos = _pos;
vel = _vel;
ltr = _ltr;
}
//FUNCTIONS
void display(){
textAlign(CENTER,BOTTOM);
text(ltr, pos.x,pos.y);
noFill();
//ellipse(pos.x,pos.y,5,5);
}
void setRandPos(){
pos = new PVector(random(0,width), 0);
}
void updatePos(){
float xPos = pos.x;
float yPos = pos.y;
int indexAhead = int(xPos)+int(yPos)*width;
int indexAbove = int(xPos)+int(yPos-aboveCheck)*width;
float aheadCol = red(pixels[indexAhead]);
float aboveCol = red(pixels[indexAbove]);
if(aheadCol>threshold){
pos.set(xPos+vel.x, yPos+vel.y,0);
}
else if(aboveCol<=threshold){
pos.set(xPos, yPos-aboveCheck,0);
}
}
boolean finished(){
return(pos.y>=height-1 || pos.y<=aboveCheck);
}
}