This complete guide walks through creating windows, setting up accelerated renderers, drawing primitives, loading fonts, rendering text, handling window events, scaling, dynamic text on keypress, and best practices for SDL2
+ SDL_ttf
.
Compile with -lSDL2 -lSDL2_ttf
.
SDL_Init(SDL_INIT_VIDEO);
TTF_Init();
SDL_INIT_VIDEO
– enables the video subsystem; combine flags (e.g., | SDL_INIT_EVENTS
).TTF_Init()
– no params; returns 0
on success.
SDL_Window* win = SDL_CreateWindow(
"Demo", /* window title */
SDL_WINDOWPOS_CENTERED, /* x position */
SDL_WINDOWPOS_CENTERED, /* y position */
800, /* width px */
600, /* height px */
SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE
);
title
– UTF‑8 C‑string shown in title‑bar.x
/y
– screen coordinates or SDL_WINDOWPOS_UNDEFINED/SDL_WINDOWPOS_CENTERED
.w
/h
– window size in logical pixels.flags
SDL_WINDOW_SHOWN
– make visible immediately.SDL_WINDOW_RESIZABLE
– allow user‑driven size change.SDL_WINDOW_FULLSCREEN
, SDL_WINDOW_FULLSCREEN_DESKTOP
, SDL_WINDOW_OPENGL
…
SDL_Renderer* ren = SDL_CreateRenderer(
win, /* window */
-1, /* driver index (‑1 = first supporting flags) */
SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC
);
SDL_SetRenderDrawBlendMode(ren, SDL_BLENDMODE_BLEND);
window
– handle from SDL_CreateWindow
.index
– GPU driver (-1 auto select).flags
SDL_RENDERER_ACCELERATED
– hardware acceleration.SDL_RENDERER_SOFTWARE
– fallback software.SDL_RENDERER_PRESENTVSYNC
– sync with display refresh.Blend mode enables transparency for textures and primitives.
bool running = true;
SDL_StartTextInput();
/* text buffer & helpers */
std::string buffer = "Type: ";
SDL_Color white = {255,255,255,255};
SDL_Texture* textTex = NULL;
TTF_Font* font24 = TTF_OpenFont("NunitoSans-Regular.ttf", 24);
auto renderText = [&](const std::string& msg){
if(textTex) SDL_DestroyTexture(textTex);
SDL_Surface* s = TTF_RenderUTF8_Blended(font24, msg.c_str(), white);
textTex = SDL_CreateTextureFromSurface(ren, s);
SDL_FreeSurface(s);
};
renderText(buffer);
while (running) {
SDL_Event e;
while (SDL_PollEvent(&e)) {
if (e.type == SDL_QUIT) running = false;
if (e.type == SDL_TEXTINPUT) {
buffer += e.text.text; /* append typed character */
renderText(buffer);
}
if (e.type == SDL_KEYDOWN && e.key.keysym.sym == SDLK_BACKSPACE && buffer.size() > 6) {
buffer.pop_back(); /* remove last char */
renderText(buffer);
}
if (e.type == SDL_WINDOWEVENT && e.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
int newW = e.window.data1;
int newH = e.window.data2;
/* handle resize */
}
}
SDL_SetRenderDrawColor(ren, 30,30,30,255);
SDL_RenderClear(ren);
/* draw dynamic text */
SDL_Rect dst; SDL_QueryTexture(textTex, NULL, NULL, &dst.w, &dst.h);
dst.x = 50; dst.y = 40;
SDL_RenderCopy(ren, textTex, NULL, &dst);
SDL_RenderPresent(ren);
}
SDL_StopTextInput();
SDL_StartTextInput()
/SDL_StopTextInput()
– enable/disable Unicode text events.SDL_TEXTINPUT
– event fired for every UTF‑8 character typed (handles IME & locale correctly).SDL_KEYDOWN
– capture non‑text keys (e.g., backspace, function keys).
TTF_Font* font24 = TTF_OpenFont("NunitoSans-Regular.ttf", 24);
TTF_Font* font48 = TTF_OpenFont("NunitoSans-Regular.ttf", 48);
file
– path to TrueType/OTF font.ptsize
– requested height in points.Reuse opened fonts to avoid reload overhead.
SDL_Surface* surf = TTF_RenderUTF8_Blended(font24, "Hello SDL2", white);
SDL_Texture* texStatic = SDL_CreateTextureFromSurface(ren, surf);
SDL_FreeSurface(surf);
SDL_Rect dst; SDL_QueryTexture(texStatic, NULL, NULL, &dst.w, &dst.h);
SDL_RenderCopy(ren, texStatic, NULL, &dst);
Use this method for labels that rarely change.
SDL_Surface* paragraph = TTF_RenderUTF8_Blended_Wrapped(
font24,
"Lorem ipsum dolor sit amet…",
white,
400 /* wrap max width px */
);
SDL_ttf handles newlines automatically.
SDL_RenderSetLogicalSize(ren, 800, 600);
Coordinates are mapped to virtual space and automatically scaled.
SDL_SetWindowFullscreen(win, SDL_WINDOW_FULLSCREEN_DESKTOP);
SDL_DisplayMode dm;
SDL_GetCurrentDisplayMode(0, &dm);
printf("%dx%d @ %dHz\n", dm.w, dm.h, dm.refresh_rate);
float ddpi, hdpi, vdpi;
SDL_GetDisplayDPI(0, &ddpi, &hdpi, &vdpi);
if(!win || !ren){ fprintf(stderr, "%s\n", SDL_GetError()); }
SDL_DestroyTexture(textTex);
SDL_DestroyTexture(texStatic);
TTF_CloseFont(font24);
SDL_DestroyRenderer(ren);
SDL_DestroyWindow(win);
TTF_Quit();
SDL_Quit();