Search code examples
c++textsdltruetype

SDL C++ TTF randomly disappears after a while (and doesn't come back)


I'm making a Yahtzee-like (a dice game with scoring) in c++ using SDL. It's my first SDL project to develop on my own.

The problem can be described as: When I start the game, text is rendering fine. I can place scores and continue the game. However, if I wait for a few minutes (whether I'm still playing or not), the text eventually ceases to render. I can continue the game, but no text will display, and the previously displayed text is no longer displayed.

I'm completely baffled by this issue. It has not happened until now, as none of the games before now were long enough for me to notice.

Note: one thing that I stumbled upon was software and hardware rendering. I'm not sure why, but I tried to render with the hardware instead, and that did not solve the problem.

Another note: The text rendering part of the code is towards the end, in a for-loop.

I'm lost, can anyone help me? I'll post the code, but it's long, ridiculous, and I don't think it is the issue.

int GUI(State& GameState)
{       
apply_surface( 0, 0, background, screen ); //background
apply_surface( SCORE_X, SCORE_Y, scoreImage, screen ); //score card
apply_surface( KEPT_TRAY_X, KEPT_TRAY_Y, keptTray, screen ); //kept tray
apply_surface( TEXT_BOX_X, TEXT_BOX_Y, textBox, screen ); //text box

//Blatantly handles only the next event on the queue per frame
if( SDL_PollEvent( &event ) )
    eventHandler(GameState);

//place button
if(GameState.placeButtonClicked)
{
    apply_surface( GameState.buttonV[GameState.placeButtonClicked].x, GameState.buttonV[GameState.placeButtonClicked].y, clickedButton, screen );
}

//dice[1]
apply_surface( *GameState.diceV[1].pointX, *GameState.diceV[1].pointY, *GameState.diceV[1].surfaceValue, screen );

//dice[2]
apply_surface( *GameState.diceV[2].pointX, *GameState.diceV[2].pointY, *GameState.diceV[2].surfaceValue, screen );

//dice[3]
apply_surface( *GameState.diceV[3].pointX, *GameState.diceV[3].pointY, *GameState.diceV[3].surfaceValue, screen );

//dice[4]
apply_surface( *GameState.diceV[4].pointX, *GameState.diceV[4].pointY, *GameState.diceV[4].surfaceValue, screen );

//dice[5]
apply_surface( *GameState.diceV[5].pointX, *GameState.diceV[5].pointY, *GameState.diceV[5].surfaceValue, screen );

//rollButton
if(GameState.navV[1].clicked)
{
    apply_surface( GameState.navV[1].x, GameState.navV[1].y, rollButtonClicked, screen);
}
else
{
    apply_surface( GameState.navV[1].x, GameState.navV[1].y, rollButton, screen );
}

//endTurnButton
if(GameState.navV[2].clicked)
{
    apply_surface( GameState.navV[2].x, GameState.navV[2].y, endTurnButtonClicked, screen );
}
else
{
    apply_surface( GameState.navV[2].x, GameState.navV[2].y, endTurnButton, screen );
}

//displaying the clickedButton if a score is clicked
if(GameState.placeButtonClicked != 0)
{
    apply_surface( GameState.buttonV[GameState.placeButtonClicked].x, GameState.buttonV[GameState.placeButtonClicked].y, clickedButton, screen );
}

//displaying the scores for each "button" (each score segment)
for(int i = 1; i <= (GameState.buttonV.size() - 1); i++)
{
    if(GameState.buttonV[i].value >= 0)
    {
        message = TTF_RenderText_Solid( scoreFont, GameState.buttonV[i].valueString, scoreFontColor );
        apply_surface( GameState.buttonV[i].x + 10, GameState.buttonV[i].y + 2, message, screen );
    }
}

if( SDL_Flip( screen ) == -1 )
{
    return 1;
}

decGUICounters(GameState);

return 0;

}


Solution

  • I found the answer browsing this website (it took a while!). Hopefully I can help someone else out with what I found:

    The problem was that I was repeatedly setting new text to message:

    message = TTF_RenderText_Solid(etc);
    

    When you call TTF_RenderText_Solid(), it returns a new surface to the surface pointer (message). However, it does not free the RAM that the old surface contained.

    All you have to do is: SDL_FreeSurface(message); before you assign new memory to the surface pointer (message).

    This prevents a memory leak, which in turn prevents your memory from randomly being obliterated by the CPU.

    TL;DR:
    
    SDL_FreeSurface(message);
    

    Before:

    message = TTF_RenderText_Solid();