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);
}
}
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);
}
}