GitHub: https://github.com/andybiar/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 | import processing.video.*; Capture cam; PFont f; PImage bg; final int WIDTH = 640; final int DARK_THRESHOLD = 120; Letter[] fallers; Letter[] droppers; int dropCount = 0; final String[] WORDS = {"H","i","m","y","n","a","m","e", "i","s","A","n","d","y","B","i", "a","r","a","d","I","l","i","k", "e","t","o","m","a","k","e","t", "h","i","n","g","s","f","o","r", "p","e","o","p","l","e","t","o", "d","i","s","c","o","v","e","r", "w","i","t","h","f","u","n","!"}; void setup() { size(WIDTH, 480); String[] cameras = Capture.list(); if (cameras.length == 0) println("No cameras"); else cam = new Capture(TextRain.this, cameras[0]); cam.start(); f = createFont("Verdana", 18, true); textFont(f); fill(10); fallers = new Letter[WIDTH/10]; droppers = new Letter[WIDTH/10]; } int nextDrop() { if (dropCount >= WIDTH/10) return -1; int rand = int(random(WIDTH/10)); while(fallers[rand] != null) { rand = (rand + 1) % (WIDTH/10); } return rand; } void draw() { // Get background from webcam if (cam.available() == true) cam.read(); image(cam, 0, 0); loadPixels(); // Drop a letter if (dropCount < 64 && (millis() / 1000) > dropCount) { int nextDrop = nextDrop(); if (nextDrop != -1) { fallers[nextDrop] = new Letter(WORDS[nextDrop%WORDS.length], nextDrop*10, 0); } dropCount++; } // Draw letters for (int i = 0; i < fallers.length; i++) { Letter n = fallers[i]; if (n != null) text(n.letter, n.x, n.y); } // Gravity for (int i = 0; i < fallers.length; i++) { if (fallers[i] != null) { Letter a = fallers[i]; if (a.y >= height || a.y < 0) continue; color c = pixels[WIDTH * a.y + a.x]; float r, g, b; r = red(c); g = green(c); b = blue(c); int brightness = int(.2989*r + .5870*g + .1140*b); if (brightness > DARK_THRESHOLD) fallers[i].y += 1; } } // Reset falling letters for(int i = 0; i < fallers.length; i++) { if (fallers[i] != null && fallers[i].y >= height) { fallers[i].y = 0; } } } public class Letter { public String letter; public int x; public int y; public Letter(String letter, int x, int y) { this.letter = letter; this.x = x; this.y = y; } } |
I think Text Rain is one of my weaker projects in the upkit intensive, but here it is. I used an object-oriented approach, creating a Letter class which stored it’s x and y position as well as the character to be drawn. Other than that, my implementation is likely pretty vanilla – I used the Capture object to get pixels from the webcam, loaded them into an array, and read points under the letters for darkness above a certain threshold. Definitely a fun starter project! Also, this is the first time in my life I have ever intentionally not shaved my stache, and I think it looks pretty good in this photo: