SDL_TTF update text each cycle - better solution?

Hi there

So I have created a score overlay for my game that displays the current score using SDL_ttf.

However, in order to always have the current score displayed, the sprite has to update every cycle of the game. The way I currently handle this is by simply deleting the sprite and creating a new one each cycle. This works fine, but comes with a hefty performance penalty. Now since we are talking about a simple 2D-game, the performance is still great. The game runs at 4500 FPS without the score overlay and still about 1000 FPS with it, which is of course more than enough. But you can clearly see the massive drop just from implementing this overlay.

I feel that with bigger projects in the future, running more of these overlays, this might become a problem. So I'm wondering if there is a more performance-friendly solution to update the SDL_ttf texture each cycle.

Below the relevant code that is run every game-cycle (at least I hope I found everything ;) ).

1
2
3
4
5
6
7
8
9
10
11
12
13

if (m_pSprite_Score != NULL)		// if score-sprite exists => destroy
{
	delete (m_pSprite_Score);
	m_pSprite_Score = NULL;
}

m_pSprite_Score = new C_Sprite;		// then create a new instance of the score sprite

m_sScore = std::to_string(m_Score);		// convert int score to string
m_pSprite_Score->Display_Text("Data/Fonts/arial.ttf", m_sScore, 50, 20.0f, 20.0f, 50, 200, 50);		// update the score-sprite
m_pSprite_Score->Render();
			


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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

// Constructor
//
// Purpose: Get Pointer to Renderer
//
C_Sprite::C_Sprite()
{
	m_pRenderer = g_pFramework->Get_Renderer();

}// Constructor


// Destructor
//
// Purpose: Terminate Sprite
//
C_Sprite::~C_Sprite()
{
	SDL_DestroyTexture(m_pImage);

}// Destructor


// Display Text (fixed position)
//
// Purpose: Display Text on the Screen
//
void C_Sprite::Display_Text(const std::string sFont, const std::string sText, int Size, float fX_Position, float fY_Position, int R, int G, int B)
{
	TTF_Font * pFont = TTF_OpenFont(sFont.c_str(), Size);

	SDL_Color Color = { R, G, B };

	SDL_Surface * pTemp = TTF_RenderText_Solid(pFont, sText.c_str(), Color);

	m_pImage = SDL_CreateTextureFromSurface(m_pRenderer, pTemp);	// generate the actual sprite/texture that the renderer can then display on the screen

	// Initialize Rect
	//
	m_Rect.w = pTemp->w;					// get width for rectangle from pTemp (of type "SDL_Surface")
	m_Rect.h = pTemp->h;					// get height for rectangle from pTemp (of type "SDL_Surface")
	m_Rect.x = static_cast<int>(fX_Position);		// set x position relative to size of rect (since we are talking about text, the size can vary)
	m_Rect.y = static_cast<int>(fY_Position);		// set x position relative to size of rect (since we are talking about text, the size can vary)

	TTF_CloseFont(pFont);		// close font to free memory

	SDL_FreeSurface(pTemp);		// clear temporary surface	

}// Display Text (fixed position)


// Render (static)
//
// Purpose: Render static Sprite
//
void C_Sprite::Render()
{
	// Render Sprite
	//
	SDL_RenderCopy(m_pRenderer, m_pImage, NULL, &m_Rect);

}// Render (static)

Last edited on
Instead of creating a new SDL_Surface and creating a new texture from it each frame, you could render the text to a preallocated buffer and upload the buffer to the texture. I can't remember ATM if that flow is doable with SDL_TTF, but it is with raw TrueType.

To get the best speedup, though, you'd need to use completely different rendering method. The way you're doing it now you're rasterizing the font for each individual string you want to display. You can instead render the entire set of glyphs you need to a texture and copy portions of that texture to the screen as needed. That would be the fastest method.
Topic archived. No new replies allowed.