Day 43/100 100 Days of Code

Day 43/100 100 Days of Code

Rebuild Back Better

I did a lot of useful things today. I remembered how to frame screen refresh work, and added a font, a main menu title, a renderer, an enumerator to handle game states, and installed the SDL_ttf library.

SDL_ttf

SDL_ttf is a separate add-on library for SDL that is used for fonts and text. I added the library as a submodule, built it, and added the following in the top-level CMakeLists.txt to make it work:

# Make Sure that the program is isntalled
if(NOT EXISTS "${PROJECT_SOURCE_DIR}/modules/SDL_ttf/CMakeLists.txt")
    message(FATAL_ERROR "The submodules were not downloaded! GIT_SUBMODULE was turned off or failed. Please update submodules and try again.")
endif()

# Link ttf library
add_subdirectory("${PROJECT_SOURCE_DIR}/modules/SDL_ttf")
find_package(SDL3_ttf REQUIRED CONFIG REQUIRED COMPONENTS SDL3_ttf)
# this is inserted after the add_executable command
target_link_libraries(${PROJECT_NAME} PRIVATE SDL3_ttf::SDL3_ttf)

Then, I included the SDL_ttf header file and initialized the library.

#include <SDL3_ttf/SDL_ttf.h>

if (SDL_Init(SDL_INIT_VIDEO) != 0 || TTF_Init() != 0)
{
    std::cout << "Failed to initialise SDL ";
    std::cout << SDL_GetError() << std::endl;
    return false;
}

Window Refresh and Background Color

The window should be refreshed in each frame to remove the elements from the previous frame. The following code paints the background white in each frame.

        // Rendering
        SDL_SetRenderDrawColor(renderer,
                                 0xFF, 0xFF,
                                 0xFF, 0XFF);
        SDL_RenderClear(renderer);

        SDL_RenderPresent(renderer);
        //Ending tick
        endTick = SDL_GetTicks();
        frameTime += (endTick - startTick)/1000;

Game States

To make the game adaptive to the current state, I created a GameSate enumerator and a currentGameState integer variable to store the current state of the game.

enum GameState
{
    MAIN_MENU = 0,
    GAMEPLAY,
    PAUSED
};

static int currentGameState;

Then, I added a switch in the main game loop:

switch (currentGameState)
{
    case MAIN_MENU:
        break;

    case GAMEPLAY:
            break;

    case PAUSED:
        break;
}

Creating a renderer

To create a renderer with SDL is pretty straightforward:

SDL_Renderer *renderer;

renderer = SDL_CreateRenderer(window, nullptr, SDL_RENDERER_ACCELERATED);

Main Menu Title

First, I created the variables I needed to display the game's title and a MainMenu() method to call when the game is in the MainMenu state.

static TTF_Font *titleFont;
static void LoadMainMenu();
static SDL_Surface *titleTextSurface;
static SDL_Texture *titleTextTexture;

Then, I created a MainMenu function and used all the properties and methods needed to create the title:


void Game::LoadMainMenu()
{
    titleFont = TTF_OpenFont("/Users/chrisd/Desktop/Rebuild Back Better/fonts/ArianaVioleta-dz2K.ttf", 44);

    if (titleFont == nullptr)
    {
        std::cout << "Failed to create font" << std::endl;
        std::cout << SDL_GetError() << std::endl;
        exit(-1);
    }

    SDL_Color titleTextcolor = {0x00, 0x00, 0x00};
    titleTextSurface = TTF_RenderText_Solid(titleFont,
                                            "Rebuild Back Better",
                                            titleTextcolor);

    if (titleTextSurface == nullptr)
    {
        std::cout << "Failed to create title texture surface ";
        std::cout << SDL_GetError() << std::endl;
        exit(-1);
    }

    titleTextTexture = SDL_CreateTextureFromSurface(renderer, titleTextSurface);

    const SDL_FRect titleHolder = {static_cast<int>((float)SCREEN_WIDTH * 0.405),
                            static_cast<int>((float)SCREEN_HEIGHT * 0.2),
                            static_cast<float>(titleTextSurface->w),
                            static_cast<float>(titleTextSurface->h)};

    SDL_RenderTexture(renderer, titleTextTexture, nullptr,
                      &titleHolder);

    SDL_DestroySurface(titleTextSurface);
}

Unfortunately, I was unable to use the relative URL to the font. I am not sure why this is happening.