This guide will provide step-by-step instructions on how to add True Type Font to the Simple DirectMedia Layer (SDL) library in a Visual Studio C++ project.
About True Type Font
TrueType is an outline font standard developed by Apple in the late 1980s as a competitor to Adobe’s Type 1 fonts used in PostScript. It has become the most common format for fonts on the classic Mac OS, macOS, and Microsoft Windows operating systems.
Download SDL True Type Font
- Download the SDL_ttf (True Type Font) library
- Unzip the downloaded .zip file
- Copy the SDL2 TTF
include
and lib
directory to the existing ThirdParty/SDL2 folder- This will add the True Type Font files to SDL2
Add SDL True Type Font to the Solution Project(s)
If the Solution contains multiple Projects, the following steps will need to be done for each project. This is because each project needs the path to the SDL2 TTF includes and libraries.
SDL2 should’ve already been setup with the include directories and library directories for the projects, the only step necessary is to add the library (.lib) in the project properties.
Add SDL True Type Font Library
The sdl2_ttf.lib only needs to be added to the project that is the application (Game). Do not add it to the library project (Engine). If it is added to both, there will be a warning reported when built.
- Open the Project Properties that SDL will be used in
- Right-click the Project and select Properties
- Add the SDL2 TTF .lib files that the project needs to function
- Additional Dependencies is located in Librarian>General or Linker>General
- Add
sdl2_ttf.lib
Add SDL True Type Font Dynamic Link Library (dll)
- Create a folder in the Solution directory called “Build”
- This step may have already been completed earlier.
- The Build folder will contain the SDL TTF dll (dynamic link library) files.
- Copy the sdl2_ttf.dll file from the ThirdParty\sdl2\lib\x64 directory to the Build folder.
- The project is a x64 project (64-bit application).
If SDL2 TT2 was properly added, building and running the project will result in no errors.
Add Fonts to the Build
- Find fonts to use in the program
Update Code for SDL TTF Fonts
Add TTF Fonts to the Renderer
- In the Renderer.h header, include the SDL TTF header
- Add the code to initialize and quit SDL TTF in the Initialize() and Shutdown() method
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| bool Renderer::Initialize()
{
// initialize SDL
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
std::cerr << "Error initializing SDL: " << SDL_GetError() << std::endl;
return false;
}
// initialize TTF SDL
if (TTF_Init() < 0)
{
std::cerr << "Error initializing SDL TTF: " << SDL_GetError() << std::endl;
return false;
}
return true;
}
|
1
2
3
4
5
6
| void Renderer::Shutdown()
{
SDL_DestroyRenderer(m_renderer);
SDL_DestroyWindow(m_window);
TTF_Quit();
}
|
Create Font Class
1
2
3
4
5
6
7
8
9
10
11
| class Font
{
public:
Font() = default;
~Font();
bool Load(const std::string& name, int fontSize);
private:
_TTF_Font* m_ttfFont{ nullptr };
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| Font::~Font()
{
if (m_ttfFont != nullptr)
{
TTF_CloseFont(m_ttfFont);
}
}
bool Font::Load(const std::string& name, int fontSize)
{
m_ttfFont = TTF_OpenFont(name.c_str(), fontSize);
if (m_ttfFont == nullptr)
{
std::cerr << "Could not load font: " << name << std::endl;
return false;
}
return true;
}
|
Create Text Class
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| class Text
{
public:
Text() = default;
Text(Font* font) : m_font{ font } {}
~Text();
bool Create(Renderer& renderer, const std::string& text, const Color& color);
void Draw(Renderer& renderer, int x, int y);
private:
Font* m_font{ nullptr };
SDL_Texture* m_texture{ nullptr };
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
| Text::~Text()
{
if (m_texture != nullptr)
{
SDL_DestroyTexture(m_texture);
}
}
bool Text::Create(Renderer& renderer, const std::string& text, const Color& color)
{
// create a surface using the font, text string and color
SDL_Color c{ Color::ToInt(color.r), Color::ToInt(color.g), Color::ToInt(color.b), Color::ToInt(color.a) };
SDL_Surface* surface = TTF_RenderText_Solid(m_font->m_ttfFont, text.c_str(), c);
if (surface == nullptr)
{
std::cerr << "Could not create surface.\n";
return false;
}
// create a texture from the surface, only textures can render to the renderer
m_texture = SDL_CreateTextureFromSurface(renderer.m_renderer, surface);
if (surface == nullptr)
{
SDL_FreeSurface(surface);
std::cerr << "Could not create texture" << SDL_GetError() << std::endl;
return false;
}
// free the surface, no longer needed after creating the texture
SDL_FreeSurface(surface);
return true;
}
void Text::Draw(Renderer& renderer, int x, int y)
{
// query the texture for the texture width and height
int width, height;
SDL_QueryTexture(m_texture, nullptr, nullptr, &width, &height);
// copy the texture onto the renderer
SDL_Rect rect{ x, y, width, height };
SDL_RenderCopy(renderer.m_renderer, m_texture, NULL, &rect);
}
|
Create Text in Main
- In main() create and load a font
- Load(True Type Font Filename, Font Size)
1
2
| Font* font = new Font();
font->Load("arcadeclassic.ttf", 20);
|
- After creating the font, create the text passing the font in the constructor
- Text(Font)
- Create(Renderer, Text String, Color)
1
2
| Text* text = new Text(font);
text->Create(g_engine.GetRenderer(), "Hello World", Color{ 1, 1, 1, 1 });
|
- In the render section of the main loop, draw the text
- Draw(Renderer, X Position, Y Position)
1
| text->Draw(g_engine.GetRenderer(), 40, 40);
|
Build and run the program and the text will show up on the screen at the set location. Multiple text objects can be created to draw text for player lives and game score.