Search code examples
c++visual-studio-2013sdl-2sdl-ttf

TTF_RenderText_Solid() Crashing Game and Visual Studio [c++][sdl ttf]


Stack Trace : enter image description here

So, I'm trying to create a 2D game and right now I'm trying to display and move a image, however when I Debug the game/run it, visual studio and the game freezes and can't quit, not even when using the task manager to kill it. The only way to unfreeze it is by logging off or restarting the pc which forces both of them to close.

I also get some weird error :

Unhandled exception at 0x71002A95 (SDL2_ttf.dll) in SDLGame.exe: 0xC0000005: Access violation reading location 0x00000000.

I have no idea what it means and how to fix it, but I'm guessing it has something to do with my code that I need to change.

Here's my code :

#include <iostream>
#include <SDL.h>
#include <SDL_image.h>
#include <SDL_ttf.h>

// Macros
#define pause system("PAUSE"); // Works on windows only, removed in alpha / beta versions.

// Pre "init" of functions
void QuitGame();
int InitGame();
void processInput();
void InitRects();

// Variables
int FramesPassed = 0;
int FramesPerSecond = 0; // Not used yet

SDL_Renderer* renderer = nullptr;
SDL_Window* window = nullptr;
SDL_Event evnt;

SDL_Rect sprite1_Rect;
SDL_Rect FPS_Text_Rect;

TTF_Font* Sans = TTF_OpenFont("Fonts/Aaargh.ttf", 40);

SDL_Color Color_White = { 255, 255, 255 };

SDL_Surface* FPS_Text_Surface = nullptr;

SDL_Texture* FPS_Text = nullptr;
SDL_Texture* testImg = nullptr;

static bool isRunning = true;

int SDL_main(int argc, char* argv[])
{
    InitGame();
    InitRects();

    std::cout << "Displaying text on screen using SDL TTF doesn't work" << std::endl;
    std::cout << "This happens when the TTF Surface is being rendered on screen" << std::endl;
    std::cout << "check line : 123 and 124." << std::endl;

    while (isRunning)
    {
        FramesPassed++;

        processInput();
        SDL_RenderClear(renderer); // Clears the last/current frame?

        // Render testImage on screen. (needs to be between render present and clear.)
        SDL_RenderCopy(renderer, testImg, NULL, &sprite1_Rect);
        SDL_RenderCopy(renderer, FPS_Text, NULL, &FPS_Text_Rect);

        SDL_RenderPresent(renderer); // Pretty much draws everything again.
    }

    return 0;
    QuitGame();

}

int InitGame()
{

    std::cout << "Game Initializing..." << std::endl;
    std::cout << "TTF SDL Initializing..." << std::endl;

    if (TTF_Init() < 0)
    {
        std::cout << "SDL TTF Failed To Initialize : " << TTF_GetError() << std::endl;
        pause
        QuitGame();
    }
    else
    {

        std::cout << "SDL TTF Initialized Successfully" << std::endl;

        if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
        {
            std::cout << "SDL Initialization Failed : " << SDL_GetError() << std::endl;
            pause
                QuitGame();
        }
        else
        {
            std::cout << "SDL Initializing" << std::endl;

            window = SDL_CreateWindow("Game Title", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1024, 720, SDL_WINDOW_SHOWN);
            if (window == NULL)
            {
                std::cout << "Window Creation Failed : " << SDL_GetError() << std::endl;
                pause
                    QuitGame();
            }
            else
            {
                std::cout << "SDL Initialized Successfully" << std::endl;
                std::cout << "Renderer Initializing..." << std::endl;

                renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
                if (renderer == NULL)
                {
                    std::cout << "Renderer Creation Failed : " << SDL_GetError() << std::endl;
                    pause
                        QuitGame();
                }

                else
                {
                    std::cout << "Renderer Initialized Successfully" << std::endl;
                    // This line (under) crashes game, and crashes visual studio...
                    FPS_Text_Surface = TTF_RenderText_Solid(Sans, "Frames Passed : " + FramesPassed, Color_White);
                    testImg = IMG_LoadTexture(renderer, "images/test.bmp");
                    FPS_Text = SDL_CreateTextureFromSurface(renderer, FPS_Text_Surface);
                }
            }
        }

    }
    std::cout << "Game Has Successfully Initialized!" << std::endl;
    return 0;

}

void InitRects()
{

    sprite1_Rect.h = 32;
    sprite1_Rect.w = 32;
    sprite1_Rect.x = 10;
    sprite1_Rect.y = 10;

    FPS_Text_Rect.h = 100;
    FPS_Text_Rect.w = 50;
    FPS_Text_Rect.x = 2;
    FPS_Text_Rect.y = 2;

}

void processInput()
{
    if (SDL_PollEvent(&evnt)) {

        switch (evnt.type) {

            case SDL_QUIT:
                QuitGame();
                break;

            case SDL_KEYDOWN:

                switch (evnt.key.keysym.sym) {
                    case SDLK_a:
                        sprite1_Rect.x -= 1;
                        break;
                    case SDLK_d:
                        sprite1_Rect.x += 1;
                        break;
                    case SDLK_w:
                        sprite1_Rect.y-= 1;
                        break;
                    case SDLK_s:
                        sprite1_Rect.y += 1;
                        break;
                }

            break;

        }
    }
}

void QuitGame()
{
    isRunning = false;
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();
}

Solution

  • The problem is that you have the font as a global variable and load it straight away!

    You need to call TTF_Init() first and load the font after!

    By using a global vairable your loading it before initializing SDL_TTF, and this way TTF_OpenFont() will return a nullptr and if you try to read a nullptr gives an Access violation reading location 0x00000000 error!

    Just call TTF_OpenFont() in a function and after TTF_Init() and it will work!

    Just a tip you should check that Sans isn't a nullptr before using it!