So, I want to make a vertical line with characters (letters) in order to create something similiar to the Matrix effect. I started with a number string, just to see if it worked and it did
String character = str (floor (random(10)));
this.letter = character;
Now I want it to have letters instead of numbers, but I don't now how to make it generate randomly. I tried with char and string, but it shows more than one letter
character += char (int(random(65, 65+24)));
I've tried a new method that was recommended, but processing crashes and doesn't run it
 PVector pos;
 float speed;
 String letter;
 float change_threshold = 0.1;
 color cor = color (3, 160, 98);
 String character = "";
 // maximum letters in a string
 int maxLetters = 35;
 // which character to swap
 int charIndex = 0;
 Letter (float xpos, float ypos, float vel) {
 this.pickLetter();
 pos = new PVector (xpos, ypos);
 speed = vel;
 }
 void display() {
 for (int i = 0; i < maxLetters; i++) {
 character +=getRandomLetter() +"\n";
 }
 fill(this.cor);
 text(this.letter, this.pos.x, this.pos.y);
 float p = random(1);
 if (p < this.change_threshold && this.cor != color(255)) {
 this.pickLetter();
 }
 }
 void pickLetter() {
 //String character = str (floor (random(10)));
 //String character = new String ("a");
 //character += char (int(random(65, 65+24)));
 char randomChar = getRandomLetter();
 character = setCharAt(character, randomChar, charIndex);
 charIndex = (charIndex + 2)%character.length();
 this.letter = character;
 }
 void fall() {
 this.pos.y += this.speed;
 }
 // returns a random a-z char
 char getRandomLetter() {
 return char (int(random(65, 65+24)));
 }
 // return a new string with a char swapped at the given index
 String setCharAt(String myString, char myNewChar, int myCharIndex) {
 return myString.substring(0, myCharIndex) + myNewChar + myString.substring(myCharIndex + 1);
 }
}
2 Answers 2
Alternate method which uses an IntList to hold integers used to create letters. Numbers and corresponding letters in list are sequentially changed with each draw() cycle; frameRate may be slowed to 1 to see changes.
IntList charNum;
int y = 0;
int index = 0;
void display () {
 background(0);
 y = 30;
 for (int i = 0; i < charNum.size(); i++) {
 char a = char(charNum.get(i));
 fill(0, 192, 0);
 text(a, 60, y);
 y+=20;
 }
}
void setup() {
 size(200, 300);
 background(209);
 charNum = new IntList();
 for (int i = 0; i < 12; i++) {
 charNum.append(int(random(65, 65+24)));
 }
 display();
}
void draw() {
 frameRate(60); // Slow this to 1 to see changes
 charNum.set(index, int(random(65, 65+24)));
 display();
 index += 1;
 if (index > charNum.size() - 1) {
 index = 0;
 }
}
1 Comment
char (int(random(65, 65+24))); is indeed the right way to get a random letter.
character += char (int(random(65, 65+24))); means you append/concatenate one letter at a time therefore your character variable will increase with a new char each iteration.
character = char (int(random(65, 65+24))); would replace the current char with a new random each iteration.
If you want to make vertical text you can use the new line character (\n).
Unfortunately you can't easily swap a character out with the String class, but with a bit of substring() and concatenation you can simulate something similar. (The StringBuilder java class would make character swapping easier). Here's a commented example using String:
// full string of letters
String letters = "";
// maximum letters in a string
int maxLetters = 12;
// which character to swap
int charIndex = 0;
void setup(){
 size(300, 300);
 fill(0, 192, 0);
 textAlign(CENTER);
 textFont(createFont("Courier New", 12), 12);
 // populate the string
 for(int i = 0 ; i < maxLetters; i++){
 letters += getRandomLetter() + "\n";
 }
}
void draw(){
 // pick random char
 char randomChar = getRandomLetter();
 // replace existing characters
 letters = setCharAt(letters, randomChar, charIndex);
 // increment the char index by 2 to include \n
 // use the modulo operator to loop back to 0
 charIndex = (charIndex + 2) % letters.length();
 
 // render the text
 background(0);
 text(letters, width * 0.5, height * 0.25);
}
// returns a random a-z char
char getRandomLetter(){
 return char (int(random(65, 65+24)));
}
// return a new string with a char swapped at the given index
String setCharAt(String myString, char myNewChar, int myCharIndex){
 return myString.substring(0, myCharIndex) + myNewChar + myString.substring(myCharIndex + 1); 
}
Update The above can be encapuslated for re-use:
MText text = new MText();
void setup(){
 size(300, 300);
 fill(0, 192, 0);
 textAlign(CENTER);
 textFont(createFont("Courier New", 12), 12); 
}
void draw(){
 background(0);
 text.draw();
}
class MText{
 // full string of letters
 String letters = "";
 // maximum letters in a string
 int maxLetters = 12;
 // which character to swap
 int charIndex = 0;
 
 float x, y;
 
 MText(){
 // populate the string
 for(int i = 0 ; i < maxLetters; i++){
 letters += getRandomLetter() + "\n";
 }
 // default position
 x = width * 0.5;
 y = height * 0.25;
 }
 
 void draw(){
 // pick random char
 char randomChar = getRandomLetter();
 // replace existing characters
 letters = setCharAt(letters, randomChar, charIndex);
 // increment the char index by 2 to include \n
 // use the modulo operator to loop back to 0
 charIndex = (charIndex + 2) % letters.length();
 // render text
 text(letters, x, y);
 }
 
 // returns a random a-z char
 char getRandomLetter(){
 return char (int(random(65, 65+24)));
 }
 
 // return a new string with a char swapped at the given index
 String setCharAt(String myString, char myNewChar, int myCharIndex){
 return myString.substring(0, myCharIndex) + myNewChar + myString.substring(myCharIndex + 1); 
 }
}
The advantage of grouping/encapuslating the functionality in a class is that mulitple instances can be easily managed:
int numTexts = 60;
ArrayList<MText> texts = new ArrayList<MText>();
void setup(){
 size(300, 300);
 fill(0, 192, 0);
 textAlign(CENTER);
 textFont(createFont("Courier New", 12), 12);
 for(int i = 0 ; i < numTexts; i++){
 MText text = new MText();
 text.x = random(width);
 text.y = random(height);
 texts.add(text);
 }
}
void draw(){
 background(0);
 for(MText text: texts) text.draw();
}
class MText{
 // full string of letters
 String letters = "";
 // maximum letters in a string
 int maxLetters = 12;
 // which character to swap
 int charIndex = 0;
 
 float x, y;
 float vy;
 float textHeight;
 
 MText(){
 // populate the string
 for(int i = 0 ; i < maxLetters; i++){
 letters += getRandomLetter() + "\n";
 }
 // default position
 x = width * 0.5;
 y = height * 0.25;
 // default Y velocity
 vy = random(.16018, 2.1);
 textHeight = (textAscent() - textDescent()) * maxLetters;
 }
 
 void draw(){
 // pick random char
 char randomChar = getRandomLetter();
 // replace existing characters
 letters = setCharAt(letters, randomChar, charIndex);
 // increment the char index by 2 to include \n
 // use the modulo operator to loop back to 0
 charIndex = (charIndex + 2) % letters.length();
 // update position
 y += vy;
 if(y > height + textHeight){
 y = -textHeight * 2;
 vy = random(.16018, 2.1);
 }
 // render text
 fill(0, 192, 0);
 text(letters, x, y);
 text(0, 255, 0);
 text(letters.charAt(0), x, y);
 }
 
 // returns a random a-z char
 char getRandomLetter(){
 return char (int(random(65, 65+24)));
 }
 
 // return a new string with a char swapped at the given index
 String setCharAt(String myString, char myNewChar, int myCharIndex){
 return myString.substring(0, myCharIndex) + myNewChar + myString.substring(myCharIndex + 1); 
 }
}
Hopefully the above is a useful direction. There many ways of achieving a similar result. In terms of improvements, little touches such as a single brighter green character (maybe even making it glow), aligning x text so it doesn't overlap for the matrix 1 effect, fading/leaving trails and chaning camera z position for the matrix 2 effect, etc.
Update 2
The updated code didn't include the part instantiatting Letter and rendering it. The error I encountered was due to the fact that string was initialized to be empty (String character = "";) and the random letter function couldn't replace a character at an index that didn't exist (yet). The solution in this case would be to intialize the string with a few characters first.
For example moving:
for (int i = 0; i < maxLetters; i++) {
 character +=getRandomLetter() +"\n";
 }
in the constructor before pickLetter() gets called.
Full example:
Letter l = new Letter(150, 15, 1.5);
void setup(){
 size(300, 300);
}
void draw(){
 background(0);
 l.display();
}
class Letter{
 PVector pos;
 float speed;
 String letter;
 float change_threshold = 0.1;
 color cor = color (3, 160, 98);
 String character = "";
 // maximum letters in a string
 int maxLetters = 35;
 // which character to swap
 int charIndex = 0;
 Letter (float xpos, float ypos, float vel) {
 for (int i = 0; i < maxLetters; i++) {
 character +=getRandomLetter() +"\n";
 }
 this.pickLetter();
 pos = new PVector (xpos, ypos);
 speed = vel;
 }
 void display() {
 
 fill(this.cor);
 text(this.letter, this.pos.x, this.pos.y);
 float p = random(1);
 if (p < this.change_threshold && this.cor != color(255)) {
 this.pickLetter();
 }
 }
 void pickLetter() {
 //String character = str (floor (random(10)));
 //String character = new String ("a");
 //character += char (int(random(65, 65+24)));
 char randomChar = getRandomLetter();
 character = setCharAt(character, randomChar, charIndex);
 charIndex = (charIndex + 2)%character.length();
 this.letter = character;
 }
 void fall() {
 this.pos.y += this.speed;
 }
 // returns a random a-z char
 char getRandomLetter() {
 return char (int(random(65, 65+24)));
 }
 // return a new string with a char swapped at the given index
 String setCharAt(String myString, char myNewChar, int myCharIndex) {
 return myString.substring(0, myCharIndex) + myNewChar + myString.substring(myCharIndex + 1);
 }
}
character. If you don't want that, don't use the+=operator.