Random rows/columns in a csv file and print text with typewriter effect

Thanks…will get trying :slight_smile:

1 Like

You can try the type writer logic in a new sketch with just a String Hello You

1 Like

When you got this return to your current sketch

1 Like

Hey @Chrisir .

As you suggested i’ve been playing around with some typewriting sketches .

Based on GoToLoop/Philo post here //https://forum.processing.org/two/discussion/1823/typewrite-effect-typing-one-by-one-with-delay-on-the-strings I got one string printing to screenno problem.

I then tried to have 2 strings to print one after the other as I think this will be the way I should go with the overall sketch - for typewriter sketch two strings called one after the other, for the CSV sketch, string after string to be selected randomly:

I got it working (kind of) with using a second counter (counter2) and an else statement

String text1 = "This is the first line.";
String text2 = " And this is the second.";
PFont font;
int counter;
int counter2;

void setup() {
  size(400, 400);
  frameRate(5);
  smooth();
  font = createFont("Arial", 48);
  textFont(font, 20);
}
 
void draw() {
 
  background(150);
  fill(255);
  typewriteText();
 
}
 
void typewriteText(){
  
  if (counter < text1.length()){
    counter++;
    text(text1.substring(0, counter), 0, 40, width, height);
   
  } else {
    counter2 ++;
    text(text2.substring(0, counter2), 0, 40, width, height); 
    
  }

}

However It iterates through but then returns

out of range 25

I also tried this with just one counter, which is reset to 0, and a second if statement, it’s driving me nuts as it just keeps printing string 1 to screen.

String text1 = "This is the first line.";
String text2 = " And this is the second.";
PFont font;
int counter;
int counter2;

void setup() {
  size(400, 400);
  frameRate(5);
  smooth();
  font = createFont("Arial", 48);
  textFont(font, 20);
}
 
void draw() {
 
  background(150);
  fill(255);
  typewriteText();
 
}
 
void typewriteText(){
  
  if (counter < text1.length()){
    counter++;
    text(text1.substring(0, counter), 0, 40, width, height);
   
  } 
if (counter >= text1.length()){ //if counter is more than or equal to text1 length
     counter = 0; //sets counter to 0 which clears screen 
     text(text2.substring(0, counter), 0, 40, width, height); //prints second string to screen
    
}
}

Any pointers would be great.

That’s all good practice

Imagine processing as a good friend who is a little dumb.

You want him to do a task for you.

But you have to explain everything very precisely. You can’t assume he will do anything right by himself or intuitively.

In your first sketch you forgot to check if counter2 is exceeding the length of the string.

So you need one if inside the else-clause.

In the 2nd sketch you have to distinguish for a variable for string 1 and for string 2

ATM you are resetting the counter in the 2nd if-clause and thus the first if-clause kicks in again. Bad.

That’s how I feel about myself :rofl:

Thanks for the explanation…back to it I go :slight_smile:

You are not dumb, computers are.
You have to explain everything step by step and don’t make assumptions.

You can set a boolean flag firstStringIsFinished to true and evaluate it.

In fact with your knowledge you can now return to the main string with the table rows

Chrisir

Almost…I’m going to spend a little more time getting this right (in the sketch and my brain) and then return to the main string…thanks again!

1 Like

OK…introduced an if statement with else and reset counter2


String text1 = "This is the first line.";
String text2 = " And this is the second.";
PFont font;
int counter;
int counter2;

void setup() {
  size(400, 400);
  frameRate(5);
  smooth();
  font = createFont("Arial", 48);
  textFont(font, 20);
}
 
void draw() {
 
  background(150);
  fill(255);
  typewriteText();
 
}

void typewriteText(){
 if (counter < text1.length()){
    counter++;
    text(text1.substring(0, counter), 0, 40, width, height);
   
  } else {
   counter2++;
   text(text2.substring(0, counter2), 0, 40, width, height); 
   if (counter2 >= text2.length()){
   counter2 = 0;
    }
}

which iterates fine 1st string followed by 2nd string so I then introduced a boolean to show that string one is finished but getting a little confused…This will iterate through fine once but then second string flashes every few seconds. …I am definitely overcomplicating this !

String text1 = "This is the first line.";
String text2 = " And this is the second.";
PFont font;
int counter;
int counter2;
boolean firstStringIsFinished=true;

void setup() {
  size(400, 400);
  frameRate(5);
  smooth();
  font = createFont("Arial", 48);
  textFont(font, 20);
}
 
void draw() {
 
  background(150);
  fill(255);
  typewriteText();
 
}
 
void typewriteText(){
  
  if (counter < text1.length()){ //if counter is less than text1length Do this
    counter++; //increase counter by 
    text(text1.substring(0, counter), 0, 40, width, height); //write text to screen
    firstStringIsFinished=false; //set boolean to false
   
  } else { //if it's not do the foillowing 
    firstStringIsFinished=true;//set boolean to true
  
 if(firstStringIsFinished){ //if boolean is true 
   counter2++; //increase counter2
  
 if (counter2 >= text2.length()){ //if counter is less than text 2 
    text(text2.substring(0, counter2), 0, 40, width, height); //write text to screen
     counter2 = 0; //reset counter 2 
  }
   }
  }

}

This is inside the if-clause

Must be outside

But indeed overcomplicating

You could use my timer

You could use an array for the strings and an index variable

Not sure I understand this, as your time is linked to mills…and here millis is not necessary as ‘time’ is determined by length of specific string?

ah ok, I’ll move it outside the if clause within typewritertext()…mmm, or maybe like your earlier sketch I need to move it to void draw()…i’ll investigate!

1 Like

The timer would replace the frameRate() because you would be able to say add a letter every 1.2 seconds

2 Likes

It just takes training to beautify code

1 Like

and a lot of patience :blush:

1 Like

I am going to claim I’ve made some progress…although that might be in a two steps forwward, one step back kind of way…

I decided to start experimenting with my main sketch + typewriter effect.

After a lot of attempts I have something that is almost working…but definitely with some bugs…also I’m still a little bit confused over the use of your timer @Chrisir and am still using framerate…maybe this is where my bugs are, as in the discrepancy of using frameRate and incorporating a timer simultaneously?

Table table;
TableRow row;
int timer;
int counter = 0;
String amount="", name=""; 
String full; //a string to combine amount + name 
PFont font;


void setup() {
  size(500, 500);
  table = loadTable("mammals.csv", "header");
  timer=millis();
  smooth(); 
  font = createFont("Arial", 48); //creates font
  textFont(font, 20); //text font 
  frameRate(5); //sets framereate to 5 
  typeWriter(); //declares typeWriter fucntion 
}

void draw() {
  
  background(0);
  fill(255);
 
  text(full.substring(0, counter), 0, 40, width, height); //the text to print to screen 
  
  if(counter >= full.length()){ // if my counter is more or equal to full String  
   counter=0; //set counter back to zero 
   
 } else{  //if not 
   counter++; //increase counter by 1 which gives me typewriter effect


 }

if (millis()-timer > 10000) { //still a little confused about this 
    typeWriter(); //calls typewriter
    timer=millis(); 

   }
}

void typeWriter() {  
    
    row = table.getRow((int)random(0, 8)); //print a random row  
    amount = row.getString("amount"); //a string with amount
    name = row.getString("name"); // prints name for row
    full = amount + " " +  name;  //combines name and row into new String called full 
 
  }

My bugs that I can tell so far:

  • there is a lot of repetition, I extended the csv to have more than 3 columns (8) not…but it will pick one randomly and then print 4-5 times before selecting another one. It is never just one random selection followed by another.

  • It can be quite glitchy, it will start outputting a line and then jump to a new one - I suspect this is to do with timer/frameRate *** Actually, yes it is, when I reduce timer to 300 everything goes a bit crazy!

  • It will also occasionally (eventually) return a string out of index.

Any advice would be great!

Delete this

Instead where you say counter=0; also call the typeWriter

Rename typeWriter to selectRow

frameRate is okay

(when you want to get rid of frameRate, ask me again)

1 Like

No, this calls the function

1 Like

very happy my code is working, very annoyed/frustrated with myself for figuring out that last part - I had removed

if (millis()-timer > 10000) { //still a little confused about this 
    typeWriter(); //calls typewriter
    timer=millis(); 

   }

but didn’t call typeWriter() correctly (now called selectRow per your suggestion).

Thanks for your help and patience @Chrisir

1 Like