Larold’s Jubilant Junkyard” has become “Larold’s Retro Gameyard“. I’ve been working on this re-branding and migration for a while. All old tutorials should redirect you to this new site. If you see any errors, please let me know! See here for more information: What happened to Larold’s Jubilant Junkyard?

Drawing Text in GBDK 2020

Drawing Text in Game Boy games

Text us neccessary for every game. It explains, to the player, what is going on in your game. The Game Boy doesnt support modern fonts. In this tutorial, you’ll learn how to use the background or window to draw text.

Whether it be dialogue, the heads-up interface, or in your menus; drawing text is an essential part of game development. It guides your player and provides meaning and context for your game. Drawing text in GBDK-2020 is relatively easy, it’s just drawing tiles on the background or window.

You can find the code for this tutorial in this github repo: Drawing Basic Text. This tutorial is the first of three tutorials about drawing text with GBDK. The second tutorial will add more advanced features. The third tutorial will switch a third-party library.

If you don’t know how to draw tiles on the background, start with my other tutorial about drawing backgrounds. Once you understand the fundamentals, we’ll start by introducing our font:

This is a basic font I created in aseprite. It includes a lot of common characters used in games. We’ll use png2asset, to convert this png file into a .c and .h file. Once these files are included into our project (not shown), we’ll put the tile data into VRAM:

#include <gb/gb.h>
#include <stdint.h>
#include "font.h"

void main(void)
{
    SHOW_BKG;

    set_bkg_data(0,Font_TILE_COUNT,Font_tiles);

    ...
}

Our Character Map

We need to map our letters/numbers/symbols to tiles in VRAM. If our font tiles are placed in front of all other background tiles, here’s how the character mapping will look.

IMPORTANT NOTE: If you want to draw any backgrounds, their tiles will have to begin at index 46, to avoid any interference.

Code-wise, our character mapping looks like this:

uint8_t GetCharacterVRamTile(char character) {

    uint8_t vramTile=0;


    // Char's can be interpreted as integers
    // We don't need to map every alpha-numeric character
    // We can use basic math to simplify A-Z and 0-9
    if(character >='a' && character <= 'z')vramTile = (character-'a')+1;
    else if(character >= 'A'&&character <= 'Z')vramTile = (character-'A')+1;
    else if(character >= '0'&&character <= '9')vramTile = (character-'0')+27;
    else {
        switch(character) {
            case '!': vramTile = 37; break;
            case ':': vramTile = 38; break;
            case '?': vramTile = 39; break;
            case '/': vramTile = 40; break;
            case '=': vramTile = 41; break;
            case ',': vramTile = 42; break;
            case '.': vramTile = 43; break;
            case '<': vramTile = 44; break;
            case '>': vramTile = 45; break;
        }
    }

    return vramTile;

}

GBDK Background/Window address functions

With our font and character map explained, I’ll introduce you to two functions:

NOTE: if you want to draw on the window, use ‘get_win_xy_addr‘ instead of ‘get_bkg_xy_addr‘.

For writing a single character, we need the VRAM address for the background tile we want to draw on. To get that, we’ll use the ‘get_bkg_xy_addr‘ function. We’ll pass it the column, and row of the desired tile. It will return us a pointer to an unsigned integer.

We’ll pass that pointer, and the index for our character tile; to the second function: ‘set_vram_byte‘. That will complete the change.

NOTE: If your background/window has been moved, your text might not draw (visually) at the location you expected.

Drawing a single Character

For writing a single character, we’ll combine our character mapping and the ‘set_vram_byte‘ function:

// Get the address of the first tile in the row
uint8_t* vramAddress = get_bkg_xy_addr(column,row);

// .. then later

// we increase the vram address to move horizontally to the next tile
set_vram_byte(vramAddress++,vramTile);

We pass the above function an address, and which letter we want to draw.

Drawing Strings of Text

To draw a string of text we’ll iterate through that string, until we reach the ‘\0’ character. This character is automatically added to the end of strings when compiled.

During this process, we’ll jump to a new row every 20 characters (same as the width of the game boy, in tiles). For each row, the code will get the address of the first tile in that row, and simply increment it after drawing the letter. This is much more efficient than calling ‘get_bkg_xy_addr‘ every iteration.

void DrawText(uint8_t column, uint8_t row, char* text){

    // Get the address of the first tile in the row
    uint8_t* vramAddress = get_bkg_xy_addr(column,row);

    uint16_t index=0;

    while(text[index]!='\0'){

        char character = text[index];

        // Draw our character at the address
        // THEN, increment the address
        uint8_t vramTile = GetCharacterVRamTile(character);

        set_vram_byte(vramAddress++,vramTile);

        index++;

    }
}

Drawing text with a typewriter effect

If we want to add a typewriter effect, we can play a noise and call ‘vsync’ between iterations.

void DrawText(uint8_t column, uint8_t row, char* text){

    // Get the address of the first tile in the row
    uint8_t* vramAddress = get_bkg_xy_addr(column,row);

    uint16_t index=0;

    while(text[index]!='\0'){

        char character = text[index];

        // Draw our character at the address
        // THEN, increment the address
        uint8_t vramTile = GetCharacterVRamTile(character);

        set_vram_byte(vramAddress++,vramTile);

        index++;
            
        // Play a basic sound effect
        NR10_REG = 0x34;
        NR11_REG = 0x81;
        NR12_REG = 0x41;
        NR13_REG = 0x7F;
        NR14_REG = 0x86;

        // Wait two frames
        // This creats a typewriter effect
        // Increas the amount of 'vsync's to increase the delay per character
        vsync();
        vsync();
    }
}

Conclusion

That’s it for drawing text. You can now use this to add menus, dialogue, and more to your games. I hope you found this tutorial helpful. Check out my related github repository: Drawing Basic Text. If you want to take your text drawing to the next level, check out my tutorial on Drawing Advanced Dialogue in GBDK.

Leave a Reply

Your email address will not be published. Required fields are marked *

THANKS FOR READING!

If you have any suggestions, and/or are confused about anything: feel free to leave a comment, send me a email, or a message on social media. Constructive criticism will help the gameyard, and others like yourself. If you learned something from this tutorial, and are looking for more content, check other these other tutorials. 

Drawing Text in Game Boy games

Thanks for reading my tutorial, here are the files for that tutorial. 

Download Instructions

Unzip the attached zip file. You’ll need GBDK-2020 downloaded on your computer, and the ability to run Makefiles.  Update the GBDK_HOME environment variable, then run the make command.

If you want to make/request changes for the code, you can send me an email or put in a PR request on GitHub. Here’s a GitHub link for the code below.

Sign-Up for the "Gameyard Newsletter" for MOre Game Development News

If you like Retro Game Development, subscribe to the Gameyard Newsletter. Stay up-to-date with all the latest Game Boy news. It’s free, and you can unsubscribe any time!

Be sure to check your email inbox for a confirmation email.