You can get rid of frameRate and then use the timer only to advance the next letter
So around here
You can get rid of frameRate and then use the timer only to advance the next letter
So around here
Thanks @Chrisir
Thanks Confused yet again, not sure how to equate timer seconds to full.lenght() as this they are not comparable?
I tried
else {
timer = second(1); //timer equals a second
timer++; //timer incremenets by a second?
if (timer <= full.length()){ // if timer amount is less than full length
counter++; //increase the counter by one to give typeWriter effect
}
But obviously doesnât work .
Also, I would like to keep full on screen for 2 seconds and then clear screen for 2 seconds before starting a new iteration. Youâve already said not to use delay (), should I use the same timer?
Please distinguish between the two sketches you have now. Best save with separate names eg rowString1 and rowString2 and make a comment at the beginning of the sketches.
First one is working with frameRate
Second one is not working and is with timer
Donât mix those up.
Now
Now for the timer. The timer is always the same - measuring how much time has passed since the timer was set - you just insert what has to happen when the time (1200) has passed. Itâs like a stop watch.
The timer uses millis() which is the time since the sketch started.
At the end of setup() you say timer = millis();
And then in draw() :
if (millis()-timer > 1200) { // if 1200 millis have passed
counter++; // go to next letter
timer=millis(); // reset timer
}
and kill frameRate here or say frameRate(60);
Thus you have full control over how fast the letter appear with the timer.
Chrisir
You called it correctly but the name of the function was not the best / appropriate (in terms of its purpose/ whatâs it doing).
Thanks again @Chrisir.
For clarity, this is the sketch I am now working off //commented line by line with a description at top as you suggested.
/* This sketch randomly selects rows from a CSV file
these rows are then printed out to screen using
a 'typewriter' style effect.
*/
Table table; // table object
TableRow row; //Table row object
int timer; //creates a a timer variable
int counter = 0; //creates a counter variable and sets it to zero
String amount="", name=""; //two strings repseneting columns in csv
String full; //a string to combine amount + name
PFont font; //font
void setup() {
//size(500, 500); //size
fullScreen(); //sets output to full screen
table = loadTable("ip.csv", "header");
smooth();
font = createFont("Arial", 48); //creates font
textFont(font, 120); //text font
textAlign(CENTER, CENTER); //allings text to Center
selectRow(); //calls selectRow fucntion
timer=millis();
}
void draw() {
background(0);//background colour
fill(255);//text colour
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
selectRow(); //call selectRow()
}
if (millis()-timer > 100) { // if 1200 millis have passed
counter++; // go to next letter
timer=millis(); // reset timer
}
}
void selectRow() {
row = table.getRow((int)random(0, 3677)); //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
println (full); //just prints to serial monitor so I can test al is working
}
What I think is the final piece (for now anyway) is this idea of keeping text on screen for 2 seconds followed by a blank screen for 2 seconds .
For this my pseudocode is like this:
if ( the rows have printed out fully){
wait two seconds;
Then clear screen:
wait anther two seconds;
the go through loop again;
}
Would using a boolean be the way to go?
You could add a timer =millis (); here to make sure the first letter is displayed long enough
For your final piece: please donât use delay but use one or 2 timer
Since we have a lot of different states here (wait, show, blank, waitâŚ) I suggest to work with a variable state of type int
showing you the state you are in.
Start with switch (state) {
Google state here in the forum and see below
Chrisir
Hello,
I did not look through all the posts.
I was inspired by the âtypewriter effectâ and sharing my first rough version of code:
String s = " INCOMING TELETYPE MESSAGE TO FOLLOW... BE PREPARED!";
int x = 0;
float space;
void setup()
{
size(1000, 100, P2D);
textSize(24);
}
void draw()
{
background(0);
for(int i = 0; i <= x; i++)
{
text(s.charAt(i), i*15, 50);
}
space = 0;
if (frameCount%5 == 0)
x++;
if (x >= s.length())
x = 0;
}
My final version uses:
https://processing.org/reference/textWidth_.html for proper spacing
https://processing.org/reference/random_.html for staggered typing effect.
And other refinements.
Continue my state idea. Like water can have different states like ice, water and vapor so can have your sketch: e.g. typewrite the word, choose new row, show a blank screen etc. - as you described before. The int variable state can be 0,1,2⌠each number signifies a different state of the sketch. The variable state holds the information in which state the sketch currently is.
Having states in the sketch makes it easier for you to have precise control over the sketch and over the code. Itâs a powerful concept for handling different situations or screens. It is a powerful tool for different use cases.
E.g. in a game you have a splash screen, a game screen, a game over screen, a high score screen each with a different number of the variable state.
switch()
is like if...else if....else if.....
In each state you do what is necessary in this state (e.g. show the typewriter).
Make sure the transition from one state to the next works. Either when typewriter has shown all letters of the current variable full or when a timer is over you move on to the next state (state=2; or state++;). Also, sometimes you want to initialize the next state e.g. by setting the timer to millis().
All this is in draw(). Nothing outside the switch-clause is allowed in draw(). The state concept is a powerful concept to structure and steer a sketch/ program. You always have an exact situation the sketch is in. Instead of different boolean variables that indicate situations (partially mutually exclusiveâŚ) you have only ONE control variable state that can have different states. Nice.
Example below.
switch (state) {
case 0:
// show growing text/ typewriter
background (0);
counter++;
text(...
if(counter>=full.length()){
counter = 0; // reset
timer = millis();
state=1; // move on
}
break;
case 1:
//wait I
background (0);
if(millis()-timer>2000) {
selectRow();
state=2; // move on
}
break;
case 2:
// not necessary but never mind
state=0; // move on / reset
break;
default:
// error
println(âerrorâ);
break;
}// switch
Chrisir
Hey @Chrisir thanks for the input once again, really helpful.
Before I give this a try can I just ask you if I can call other functions within void draw using states?
As in can I still call selectRow() within draw () or I should I incorporate into draw()?
Definitely call functions from draw() but call them inside the switch () clause
In fact in much bigger sketches people just call a function in each case/break section
I was able to get the sketch to pause using your code above @Chrisir but having a little problem keeping text on screen for two seconds .
void draw() {
switch (state){ //this is the start of switch
case 0: //sets switch to 0
background (0); //background
text(full.substring(0, counter), 0, 40, width, height); //text to print
if (millis()-timer > 100) { //this is the typewriter effect
counter++; // go to next letter
timer=millis(); // reset timer
if (millis()-timer > 2000) { //if 5 seconds has passed
state=1; //go to next state
}
}
case 1:
if(counter>=full.length()){ //this if statement resets counter to 0 when text is finsihed
counter = 0; // reset
timer = millis();
state=2; // move on
}
break;
case 2: //this case makes the screen blank for 2 seconds
background (0);
if (millis()-timer > 2000) {
selectRow();
state=3;
}
break;
case 3:
state=0;
break;
}
}
As you can see I made another if Statement in the typewriter âsectionâ
My pseudo being
If ( text is on screen) {
Leave it there for two seconds}
I tried to teat âleave text on screenâ as its own state:
void draw() {
switch (state){ //this is the start of switch
case 0: //sets switch to 0
background (0); //background
text(full.substring(0, counter), 0, 40, width, height); //text to print
if (millis()-timer > 100) { //this is the typewriter effect
counter++; // go to next letter
timer=millis(); // reset timer
}
case 1:
if (millis()-timer > 2000) { //if 5 seconds has passed
state=2; //go to next state
}
break;
case 2:
if(counter>=full.length()){ //this if statement resets counter to 0 when text is finsihed
counter = 0; // reset
timer = millis();
state=3; // move on
}
break;
case 3: //this case makes the screen blank for 2 seconds
background (0);
if (millis()-timer > 2000) {
selectRow();
state=4;
}
break;
case 4:
state=0;
break;
}
}
But this returned a string out of range error.
Remember to close each case section with break !!!
mmmm, option with 4 cases
void draw() {
switch (state){ //this is the start of switch
case 0: //sets switch to 0
background (0); //background
text(full.substring(0, counter), 0, 40, width, height); //text to print
if (millis()-timer > 100) { //this is the typewriter effect
counter++; // go to next letter
timer=millis(); // reset timer
}
break; //break for case 0
case 1:
if (millis()-timer > 2000) { //if 5 seconds has passed
state=2; //go to next state
}
break; //break for case 1
case 2:
if(counter>=full.length()){ //this if statement resets counter to 0 when text is finsihed
counter = 0; // reset
timer = millis();
state=3; // move on
}
break; //break for case 2
case 3: //this case makes the screen blank for 2 seconds
background (0);
if (millis()-timer > 2000) {
selectRow();
state=4;
}
break; //break for case 3
case 4:
state=0;
break; //final break
}
}
still returns out of range error, as does 3 cases
void draw() {
switch (state){ //this is the start of switch
case 0: //sets switch to 0
background (0); //background
text(full.substring(0, counter), 0, 40, width, height); //text to print
if (millis()-timer > 100) { //this is the typewriter effect
counter++; // go to next letter
timer=millis(); // reset timer
if (millis()-timer > 5000) { //if 5 seconds has passed
state=1; //go to next state
}
}
break; // break for case 0
case 1:
if(counter>=full.length()){ //this if statement resets counter to 0 when text is finsihed
counter = 0; // reset
timer = millis();
state=2; // move on
}
break; //break for case 1
case 2: //this case makes the screen blank for 2 seconds
background (0);
if (millis()-timer > 2000) {
selectRow();
state=3;
}
break; //break for case 2
case 3:
state=0;
break; //break for final break
}
}
Not really! Itâs more that this section will be executed in the case that state is 0.
You need this if clause in the section where state is 0 !!
Here you increase counter, here you need to check it.
Do you mean I increase counter and check it in state 0?
Yes of course
Otherwise it will exceed full.length()
You can put all that in a function typewriter (that you call from case 0)
Also, remember to use ctrl-t regularly in processing to get auto indents / format
Chrisir
Thanks @Chrisir
I havenât created a function typewriter yet as Iâm still trying to get it to work. But to be honest, Iâm going around in circles (or loops).
I moved
if(counter>=full.length()){
up to case 0 per your suggestion, however this was just looping the same data each time.
So I moved tableRow()
up to case 0 âŚwhich will now change data each iteration but now it no longer pauses between iterations and I still canât get the text to stay on screen, so back to where I started yesterday morning.
void draw() {
switch (state){ //this is the start of switch
case 0: //this will be exectued if state = 0
background (0); //background
text(full.substring(0, counter), 0, 40, width, height); //text to print
if (millis()-timer > 100) { //this is the typewriter effect
counter++; // go to next letter
timer=millis(); // reset timer
}
if(counter>=full.length()){ //this if statement resets counter to 0 when text is finsihed
counter++;
selectRow();
counter = 0; // reset
if (millis()-timer > 5000) { //if 5 seconds has passed
state=1; //go to next state
}
}
break; // break for case 0
case 1: //this will be exectued if state = 1
timer = millis();
state=2; // move on
//}
break; //break for case 1
case 2: ////this will be exectued if state = 2
if (millis()-timer > 2000) {
//selectRow();
state=3;
}
break; //break for case 2
case 3:
state=0;
break; //break for final break
}
}
Think I got it
This seems to work. @Chrisir if you wouldnât mind taking a look a the code, Iâve tested it for the last 15 minutes and seems to be stable.
/* This sketch randomly selects rows from a CSV file
these rows are then printed out to screen using
a 'typewriter' style effect.
I want to thetext to print out and then stay on screen for 5 seconds
I then want the screen to stay blank for 5 seconds before starting again.
*/
int state;
Table table; // table object
TableRow row; //Table row object
int timer; //creates a a timer variable
int counter = 0; //creates a counter variable and sets it to zero
String amount="", name=""; //two strings repseneting columns in csv
String full; //a string to combine amount + name
PFont font; //font
void setup() {
size(1000, 1000); //size
// fullScreen(); //sets output to full screen
table = loadTable("ip.csv", "header");
smooth();
font = createFont("Arial", 48); //creates font
textFont(font, 120); //text font
textAlign(CENTER, CENTER); //allings text to Center
selectRow(); //calls selectRow fucntion
timer=millis();
typeWriter();
}
void draw() {
switch (state) { //this is the start of switch
case 0: //this will be exectued if state = 0
background (0); //background
text(full.substring(0, counter), 0, 40, width, height); //text to print
if (millis()-timer > 100) { //this is the typewriter effect
counter++; // go to next letter
timer=millis(); // reset timer
}
typeWriter();
break; // break for case 0
case 1: //this will be exectued if state = 1
if (millis()-timer > 5000) { //if 5 seconds has passed
timer=millis();
state=2; // move on
}
break; //break for case 1
case 2: ////this will be exectued if state = 2
background(0);
if (millis()-timer > 5000) {
selectRow();
state=3;
}
break; //break for case 2
case 3:
state=0;
break; //break for final break
}
}
void typeWriter() {
if (counter>=full.length()) { //this if statement resets counter to 0 when text is finsihed
counter++;
counter = 0; // reset
state=1;
}
}
void selectRow() {
row = table.getRow((int)random(0, 3677)); //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
println (full); //just prints to serial monitor so I can test al is working
}
Well done!
Congratulations!
A few remarks.
Remark
if (counter>=full.length()) {
counter++; **// not necessary here !!!!**
counter = 0; // reset
just use if (counter > full.length()) {
Remark
Not necessary to call typeWriter(); from setup()
The function typeWriter()
The function typeWriter() could hold more code:
void typeWriter() {
text(full.substring(0, counter),
0, 40, width, height); //text to print
if (millis()-timer > 100) { //this is the typewriter effect
counter++; // go to next letter
timer=millis(); // reset timer
}
if (counter>=full.length()) { //this if statement resets counter to 0 when text is finsihed
counter = 0; // reset
state=1;
}
}
Remark
You can move some variables into functions, when the variables are only used there.
Remark
This is unnecessary, in case 2 you can go to 0 directly
case 3:
state=0;
break; //break for final break
Here is my version:
/* This sketch randomly selects rows from a CSV file
these rows are then printed out to screen using
a 'typewriter' style effect.
I want the text to print out and then stay on screen for 5 seconds.
I then want the screen to stay blank for 5 seconds before starting again.
*/
int state=0; // state of the program
Table table; // table object
int timer; //creates a a timer variable
int counter = 0; //creates a counter variable and sets it to zero
String full; //a string to combine amount + name
void setup() {
size(1000, 1000); //size
// fullScreen(); //sets output to full screen
PFont font; //font
table = loadTable("ip.csv", "header");
smooth();
font = createFont("Arial", 48); //creates font
textFont(font, 120); //text font
textAlign(CENTER, CENTER); //aligns text to Center
selectRow(); //calls selectRow fucntion
timer=millis();
// typeWriter();
}
void draw() {
switch (state) { //this is the start of switch
case 0:
// this will be exectued if state = 0
// the typewriter
background (0); //background
typeWriter();
break; // break for case 0
case 1:
// this will be exectued if state = 1
// the text stays on screen for 5 seconds.
if (millis()-timer > 5000) { //if 5 seconds has passed
timer=millis();
state=2; // move on
}
break; //break for case 1
case 2:
// this will be exectued if state = 2
// the screen stays blank for 5 seconds before starting again.
background(0); //background
if (millis()-timer > 5000) {
selectRow();
state=0;
}
break; //break for case 2
//
}//switch
}//func
// ---------------------------------------------------------------------
void typeWriter() {
text(full.substring(0, counter),
0, 40, width, height); //text to print
if (millis()-timer > 100) { //this is the typewriter effect
counter++; // go to next letter
timer=millis(); // reset timer
}
if (counter > full.length()) { //this if statement resets counter to 0 when text is finished
counter = 0; // reset
state=1;
}
}
void selectRow() {
TableRow row; //Table row object
String amount="", name=""; //two strings representing columns in csv
row = table.getRow((int)random(table.getRowCount())); //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
// println (full); //just prints to serial monitor so I can test all is working
}
//
Congratulations again!!!
Chrisir