Development Environment: MacOS
Reference Link: Chen Yun's SDL2 Tutorial
Note: Study Notes
Drawing Text#
To draw text, you need to have a font library. My suggestion is to use the Source Han Sans font or the DeYi font created by the Bilibili user oooooohmygosh. Both fonts are open source and free.
You also need to download the SDL2_image
library:
Use brew to download: brew install sdl2_image
Then use brew info sdl2_image
to check the location.
Finally, configure CMake as follows:
cmake_minimum_required(VERSION 3.23.2)
project(DrewText C)
set(CMAKE_C_STANDARD 11)
# SDL2
set(SDL_DIR /usr/local/Cellar/sdl2/2.26.0)
include_directories(${SDL_DIR}/include/SDL2)
link_directories(${SDL_DIR}/lib/)
# SDL2_image
set(SDL2_image /usr/local/Cellar/sdl2_image/2.6.2)
include_directories(${SDL2_image}/include/)
link_directories(${SDL2_image}/lib/)
# SDL2_ttf
set(SDL2_ttf /usr/local/Cellar/sdl2_ttf/2.20.1)
include_directories(${SDL2_ttf}/include/)
link_directories(${SDL2_ttf}/lib/)
link_libraries(SDL2)
link_libraries(SDL2_image)
link_libraries(SDL2_ttf)
# Move the executable file out to prevent resource (ttf/image) not found
set(EXECUTABLE_OUTPUT_PATH ../)
add_executable(DrewText main.c)
Open the font in the main
function:
/* Open the font */
font = TTF_OpenFont("font file path", FONT_SIZE);
if (font==NULL) {
SDL_Log("Can not open font");
}
Don't forget to release it:
...
/* Close the font */
TTF_CloseFont(font);
...
Then, create a draw
function to render the text:
void draw(SDL_Surface * screen, SDL_Window * win) {
// Render text
/* Font color */
SDL_Color color = {225, 0, 0, 255}; // RGBA
/* Render the text */
SDL_Surface * text = TTF_RenderUTF8_Blended(font, "I really like you, Dong Xuelian", color); // Font, content, font color
/* Display on the main screen */
// Source rectangle
SDL_Rect text_src = {0, 0, text->w, text->h};
// Render to
SDL_BlitSurface(text, &text_src, screen, &text_src);
// Update the main screen
SDL_UpdateWindowSurface(win);
}
Then, you can run the program.
Frame Rate Detection#
First, what is frame rate?
Frame rate is a measure used to indicate the number of frames being displayed per second. The unit of measurement is "frames per second" (FPS) or "hertz". FPS is commonly used to describe how many frames are played per second in videos, electronic graphics, or games. -- Wikipedia
Implementing frame rate detection is quite simple. We just need to know the time when the rendering starts and subtract it from the time when it ends to get the current frame rate.
So, we need to set a value at the beginning of the program's main loop. SDL2 provides the SDL_GetTicks()
function to easily get the time when the program starts:
/* Frame rate: Get the millisecond value */
long begin = SDL_GetTicks();
Then, subtract the start time from the end time:
/* Frame rate: Current value */
long current = SDL_GetTicks();
/* Time spent per frame */
long cost = current - begin;
We can also lock the frame rate to maintain a stable value:
// Set the frame rate
#define FRAMERATE 60
...
/* Time per frame */
long frame = 1000/FRAMERATE;
/* Calculate the delay time to maintain the frame rate */
long delay = frame - cost;
/* If the delay is negative, do not delay to maintain the frame rate */
if (delay > 0) {
SDL_Delay(delay);
}
/* In the case of sufficient system resources, it can maintain a sufficient frame rate. If not, there is nothing we can do */
About the Viewport#
Setting the viewport allows you to conditionally limit the display of everything.
For example, if I want everything to be displayed within a 300*300 matrix at x=10
, y=50
, I can write:
// Viewport parameters
struct SDL_Rect viewport = {10, 50, 300, 300};
// renderer is the renderer
SDL_RenderSetViewport(renderer, &viewport);
You will find that everything rendered with the renderer is now confined to the target box.