[LibGDX] Cinematic text rendering

So I’ve noticed that a lot of games these days tend to render their text one character at a time (usually with typing sound effects playing), to gradually show it to the user. I’m trying to find the best way to do this in LibGDX but I just can’t produce the right time keeping mechanism.

So far I have:


public void renderCinematicString(String string, BitmapFont font, Vector2 pos, Color color){

	for(int i = 0; i < string.length(); i++){
        //TODO timing mechanism to wait x amount of milliseconds
		font.draw(spriteBatch, string.charAt(i)+"", pos.x + (i * spacing * font.getBounds(" ").width), pos.y);
	}
		
}

Any suggestions? Please tell me if anything’s unclear.

Thanks :slight_smile:

You could pass in a “time started” parameter for your timing mechanism. It would be the millisecond time when you first started drawing the text.

public void renderCinematicString(String string, BitmapFont font, Vector2 pos, Color color, long timeStarted, long timeToTake){
   
   float percentageToRender = MathUtils.clamp(Math.round((System.currentTimeMillis() - timeStarted) * 1f / timeToTake));
   int charsToRender = MathUtils.clamp(percentageToRender * string.length(), 0, string.length());
   
   for(int i = 0; i < charsToRender; i++){
      font.draw(spriteBatch, string.charAt(i)+"", pos.x + (i * spacing * font.getBounds(" ").width), pos.y);
   }
      
}

I get the percentage of text to render using (elapsed time) / (total time). The rest should be obvious from there.

I have never thought about how to implement it until now, so here is a way you could implement it.

First of all you do not want a loop. If you use a loop, its always going to render the entire string each frame.

Use an if statement, that checks to see if a certain amount of time has passed since the last character appended to the output.

Have a variable that stores the entire string, and append one character to the end of the output, and remove that character from the variable that stores the entire string.

Which should produce one character appearing at a time at a fixed time.

I have done this already.


public float textDrawLength = 0.0f;
public static float TEXTSPEED = 1f;
public String currentTextString = "";

//in gameloop:
if ((int)textDrawLength < currentTextString.length())
{
	textDrawLength+=(0.5f*TEXTSPEED);
}

//somehow/when in render:
font.drawWrapped(batch, currentTextString.substring(0, (int)textDrawLength), someX, someY, size of your text box - padding);


currentTextString is always filled with whatever string shall be in the textbox right now. Advancing the script will change this string

Hey thanks man, I’m currently using your approach. But lets take this one step further. Can each individual character have a decreasing/increasing alpha to fade in/out? I have a feeling we would have to change everything and render each character separately instead of appending to one string.

I would assume you mean that each letter fades in rather than just appearing.

In that case you would have a float eg alphaLetter = 0f, which is 0f
in the gameloop increase that 0 to 1.0f with a certain SPEED, when it has reached 1f THEN go one letter further with the old code.
(you can also play a sound per letter which some games do, sometimes its nice, but can be easily annoying when done wrong)
and then you just use that alpha on that letter.

well you would have to render twice in that case actually.
once time the old string, and one time only the current new letter with the alpha value

so there will be an extra draw for the new letter

but thats all there is to it. rest is checking if it looks nice