How to load text one letter by another?

Hi everyone,

This is my first post on here. And I’m creating my first project using OF.

I am trying to load some text with a typewriter effect, i.e. not having them drawn to the screen all at once, but one letter by another. But I don’t know how to do this.

Can anyone point me to some methods that can be of use in my case? Thanks a lot :smiley:

Here is some sudo code

in .h

string fullText;
string textToDraw; 
int timeBeginWait; 

in .cpp

//in setup;
fullText="hello world. Let's type this out letter by letter"
textToDraw =""; 
timeBeginWait = ofGetElapsedTimeMillis(); 

// in update
//determine if a second has passed between the last letter appearence
bool isTime = (ofGetElapsedTimeMillis() - timeBeginWait) >= 1000; 
if( (fullText.size() > textToDraw.size() ) & isTime ){
    // add one letter to the text to draw
    textToDraw += fullText[textToDraw.size() + 1]
    //reset the time to wait
    timeBeginWait = ofGetElapsedTimeMillis(); 
} 

// inDraw
ofDrawBitmapString(textToDraw, 100,100);
1 Like

In words what the code is doing is the following:

  1. create 2 strings, one empty, one with the full string.

  2. slowly add letters to the empty one.

  3. draw the partially created string to the screen.

Very helpful! Works perfectly.
Thank you so much, Caroline!

1 Like

Hi @Yilei_Zhang,

I didn’t test the below code. I write it now from mind. But something like that should create a typewriter effect. (This is for 1 line)

ofApp.h

    string text;
    uint64_t elapsedtime, lettertimediff;
    ofTrueTypeFont font;
    int letterno, marginleft, margintop;
    int nextletterx, nextlettery;

ofApp:cpp

void ofApp::setup() {
    text = "typewriter effect test..";
    elapsedtime = 0;
    lettertimediff = 250; //this makes 1/4 second. You can adjust this for a better timing.
    letterno = 0;
    font.loadFont("yourfont.ttf");
    marginleft = 100;
    margintop = 200;
    nextletterx = marginleft;
    nextlettery = margintop;
    ofResetElapsedTimeCounter();
}

void ofApp::draw() {
    if (letterno < text.length()) {
        elapsedtime = ofGetElapsedTimeMillis();
        if (elapsedtime >= lettertimediff) {
            font.drawString(text.substr(letterno, 1), nextletterx, nextlettery);
            nextletterx += font.stringWidth(text.substr(letterno, 1));
            letterno++;
            ofResetElapsedTimeCounter();
        }
    }
}
1 Like

Hi!

Here’s one way to go about the string creation part, paste this into your draw()

string thisIsMyText = "This is a long text, being typed out one letter at a time.\nIt has breaklines so we could make this          \n\nmore..              \n\n\n\n\ndramatic.                           ";
float timePerLetter = 0.1;
float timeToTakeToType = thisIsMyText.length() * timePerLetter;
float time = ofGetElapsedTimef();
time = fmodf( time, timeToTakeToType );
string drawString = thisIsMyText.substr( 0, ofMap(time, 0.0, timeToTakeToType, 0, thisIsMyText.length()-1 ));
ofDrawBitmapString( drawString, 0, 10 );
1 Like