0

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);
 }
}
1
  • 1
    Are you actually using the Processing programming language? If so, please update your title to summarize the problem you have (because right now it sounds like you just want to process a string, which is not a problem description). As for "I want a single character": you're showing code that very intentionally adds letters to character. If you don't want that, don't use the += operator. Commented Dec 23, 2021 at 17:38

2 Answers 2

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;
 }
}
answered Dec 26, 2021 at 23:00
Sign up to request clarification or add additional context in comments.

1 Comment

nice solution (+1). what I like about your approach is that because each character is rendered indepedently which would make it easier for example to render a single char in a brighter shade of green or make other per character changes.
1

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);
 }
}
answered Dec 26, 2021 at 4:53

5 Comments

When I add the String setChartAt, processing crashes... I don't know why this isn't working in my code, it's weird. But your solution makes sense to me and it should work when I put it onto my code
The Processing editor crashes completely (or the sketch stops with a runtime error) ? Would you be able to post an update to your question including the sketch as you describe it above, crashing ? (maybe there's something in the mix of code that isn't 100% yet)
I'll post the update.. But, basically, the code doesn't even start to run
@MariaNolasco I think the error was due to attempting to change a character at an index that didn't exist (since the string was empty). I've posted an example above.
It's working now! It's not perfect, and think it's doubling the characters, but that's probably due to the other classes I have, so I will take a look into it. But thank you very much!

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.