16. Scrolling Text

In these notes you will learn:

  • How to make upwards-scrolling movie credits.
  • How to make movie credits that fade away.

16.1. Introduction

Now that we’ve seen how to use strings and fonts, let’s look at an interesting animation example: scrolling text.

You’ve no doubt seen dozens of credit-lists at the end of movies and TV shows that slowly up the screen. In this note, we’ll write some programs that simulate movie credit scrolls.

Specifically, suppose we want to scroll these credits from the show A Game of Thrones:

              A Game of Thrones.

Peter Dinklage        ...       Tyrion Lannister
Emilia Clarke         ...       Daenerys Targaryen
Kit Harington         ...       Jon Snow

16.2. Program 1: Basic Upwards Scrolling

Since we only have 4 lines (and a blank line) to display, we’ll hold each one in a separate String variable:

String line1;
String line2;
String line3;
String line4;

void setup() {
    // ...
    line1 = "A Game of Thrones."
    line2 = "Peter Dinklage        ...       Tyrion Lannister";
    line3 = "Emilia Clarke         ...       Daenerys Targaryen"
    line4 = "Kit Harington         ...       Jon Snow"
    // ...
}

Notice that we did not include the spacings for line 1, or extra blank line. Storing strings like this can become tiresome quickly. Later on in the course we’ll see that arrays are usually a better way of storing multiple strings.

Before we worry about scrolling, let’s first neatly display these three strings on the screen

PFFont font;

float x, y; // (x, y) is the position of the first actor line.

float lineSep; // Distance between each line.

String line1;
String line2;
String line3;
String line4;

void setup() {
    size(750, 500);
    font = loadFont("Papyrus-48.vlw"); // this better be in the data folder
    textFont(font);

    x = 20;
    y= 499;
    lineSep = textAscent() + 5;

    line1 = "A Game of Thrones";
    line2 = "Peter Dinklage     ...       Tyrion Lannister";
    line3 = "Emilia Clarke         ...       Daenerys Targaryen";
    line4 = "Kit Harington        ...       Jon Snow";

}

void draw() {
    background(255);

    float titleOffset = (textWidth(line2) - textWidth(line1))/ 2;

    // Draw the title in red
    fill(200, 0, 0);
    text(line1, x + titleOffset, y - 2*lineSep());

    // the rest in black
    fill(0);
    text(line2, x, y);
    text(line3, x, y + lineSep);
    text(line4, x, y + 2 * lineSep);
}

Here we use variables x and y to denote the position of the first actor ... character line of text, and position the other lines relative to that line (in our case line2):

  • If we were to position the title at the same x position as line2, there would be textWidth(line2) - textWidth(line1) pixels between the end of line2 and the end of line1. Since we want the title to be centred, we will start line1 at x plus half that many pixels, at x + (textWidth(line2) - textWidth(line1)) / 2. For readability, we store this in a variable.
  • Note that we initialized the lineSep variable to be the value of lineAscent(), which we saw earlier is the height of the text when font is used, plus some “padding”.
  • Since we want a blank line between the title and the actor lines, we place the title at y, the position of the first actor line, minus twice the value of lineSep - one for the blank line, and one for the title line.
  • The 2nd and 3rd actor lines are placed using similar reasoning.

Now getting the scrolling to work is not too hard. All we need to do is add a dy variable:

PFFont font;

float x, y; // (x, y) is the position of the first actor line.

float dy;

float lineSep; // Distance between each line.

String line1;
String line2;
String line3;
String line4;

void setup() {
    size(750, 500);
    font = loadFont("Papyrus-48.vlw"); // this better be in the date folder
    textFont(font);

    x = 20;
    y= 499;
    dy = -1;
    lineSep = textAscent() + 5;

    line1 = "A Game of Thrones";
    line2 = "Peter Dinklage     ...       Tyrion Lannister";
    line3 = "Emilia Clarke         ...       Daenerys Targaryen";
    line4 = "Kit Harington        ...       Jon Snow";
}

void draw() {
    background(255);

    float titleOffset = (textWidth(line2) - textWidth(line1))/ 2;

    // Draw the title in red
    fill(200, 0, 0);
    text(line1, x + titleOffset, y - 2*lineSep());

    // the rest in black
    fill(0);
    text(line2, x, y);
    text(line3, x, y + lineSep);
    text(line4, x, y + 2 * lineSep);

    y += dy;
}

16.3. Program 2: Stopping and Fading Away

One of the many variations on credit-scrolling is to have the text scroll up to the middle of the screen, stop, and then fade away. To achieve this, we will have to make a few modifications to our previous program:

  1. We will need to check when the text has reached the middle of the screen This is simply a variation on checking for the edges of the screen, which we’ve seen many times.

  2. Add code to cause the text to fade away. We’ve seen this before in Special Effects: A Fading Circle, and we’ll use the same technique here. Specifically, we’ll add two new float variables:

    • transparency is a value between 0 and 1 that represents the current level of transparency for the on-screen text.
    • dt is the rate at which the transparency changes.

    We’ll also need to update our calls to fill() to include the new transparency values.

Here is the entire program:

PFFont font;

float x, y; // (x, y) is the position of the first actor line.

float dy;

float lineSep; // Distance between each line.

// transparency variables
float transparency, dt;

String line1;
String line2;
String line3;
String line4;

void setup() {
    size(750, 500);
    font = loadFont("Papyrus-48.vlw"); // this better be in the date folder
    textFont(font);

    x = 20;
    y= 499;
    dy = -1;
    lineSep = textAscent() + 5;
    transparency = 1;
    dt = 0;

    line1 = "A Game of Thrones";
    line2 = "Peter Dinklage     ...       Tyrion Lannister";
    line3 = "Emilia Clarke         ...       Daenerys Targaryen";
    line4 = "Kit Harington        ...       Jon Snow";
}

void draw() {
    background(255);

    float titleOffset = (textWidth(line2) - textWidth(line1))/ 2;
    float newTrans = map(transparency, 0, 1, 0, 255);

    // Draw the title in red
    fill(200, 0, 0, newTrans);
    text(line1, x + titleOffset, y - 2*lineSep());

    // the rest in black
    fill(0, newTrans); // Processing reads this as fill(0, 0, 0, newTrans)
    text(line2, x, y);
    text(line3, x, y + lineSep);
    text(line4, x, y + 2 * lineSep);

    // move the text
    y += dy;

    // change the transparency.
    transparency = constrain(transparency + dt, 0, 1);

    if (y < 200) {
        dy = 0; // stop the text
        dt = -0.01; // start fading
    }
}

16.4. Questions

  1. Describe the purpose of the lineSep variable.

16.5. Programming Questions

  1. Modify the first credit scroll program so that the credits scroll down instead of up. They should start entirely off the screen and then scroll down and off the bottom
  2. Modify the first credit scroll program so that the credits scroll from left to right. The credits should just scroll off the right edge of the screen.
  3. Modify the first credit scroll program so that the credits continuously “bounce” from left to right and right to left at a constant speed. No part of any of the credits should ever be off the screen.
  4. Write a program that displays the four strings in the sample programs as follows: the screen starts out empty, and the first name slowly fades in, stays on the screen for a while, and then slowly fades out. Then the next three names appear and disappear in the same way.