Day 68/100 100 Days of Code

Day 68/100 100 Days of Code

I created 2 new methods to remove a lot of lines of code. The the first method loads the fonts to the memory and the other one instantiates a new TextElement object. The second method doesn't sound useful but it made the code much more cleaner because it reduced the amount of code that is being repeated and made multi-platform code easier to handle.

But, how did it make things better?

I use many template arguments in the TextElement object, and when combined with the number of arguments the TextElement constructor requires, it's clear that this can lead to readability issues.

new TextElement<    SDL_Surface, 
                    SDL_Texture, 
                    SDL_Color, 
                    TTF_Font,
                    SDL_Renderer, 
                    AudioPlayer<Mix_Chunk>>(windowWidth * posX, 
                                            windowHeight * posY, 
                                            font, 
                                            renderer);

Before creating the method, this code was used repeatedly across three different platforms and text.

TextElement<SDL_Surface, SDL_Texture, SDL_Color, 
            TTF_Font, SDL_Renderer,
            AudioPlayer<Mix_Chunk>> *Game::LoadTextElement(    TTF_Font *font, int inputWindowWidth, 
                                                            int inputWindowHeight, float posX, 
                                                            float posY    )
{
    return new TextElement<    SDL_Surface, 
                               SDL_Texture, 
                               SDL_Color, 
                               TTF_Font,
                               SDL_Renderer, 
                               AudioPlayer<Mix_Chunk>>(windowWidth * posX, 
                                                       windowHeight * posY, 
                                                       font, 
                                                       renderer);                                                    
}

This is much better.


    if (menuStart == nullptr)
    {
        #ifdef __APPLE__
        menuStart = LoadTextElement(    menuFont, execpath + std::string("/Contents/Resources/audio/menulightup/lightup.wav"),
                                        windowWidth, windowHeight, 0.428, 0.5);
        #endif

        #ifdef _WIN64
        menuStart = LoadTextElement(    menuFont, execpath + std::string("C:/Users/chris/Desktop/Rebuild_Back_Better/resources/audio/menulightup/lightup.wav"),
                                        windowWidth, windowheight, 0.428, 0.5);
        #endif

        #ifdef __linux__
        menuStart = LoadTextElement(    menuFont, execpath + std::string("/home/vmware-ubuntu/Desktop/Rebuild_Back_Better/audio/menulightup/lightup.wav"),
                                        windowWidth, windowheight, 0.428, 0.5);
        #endif

    }

The LoadMenuFonts method loads the menu's font and is called within the LoadMainMenu() method to streamline the gameplay loop's switch case.

void Game::LoadMenuFonts(std::string path1, std::string path2)
{
    auto getTitleFont = std::async(    std::launch::async, LoadFont, 
                                    path1,
                                    150);    

    auto getMenuFont = std::async(    std::launch::async, LoadFont, 
                                    path2,
                                    60);

    getTitleFont.wait();
    getMenuFont.wait();                                  
    titleFont = getTitleFont.get();
    menuFont = getMenuFont.get();


    if (titleFont == nullptr)
    {
        std::cout << "Title font has not loaded" << std::endl;
        exit(-1);
    }

    if (menuFont == nullptr)
    {
        std::cout << "Menu font has not loaded" << std::endl;
        exit(-1);
    }

    menuFontsLoaded = true;
}

I manage to cut more than 100 lines thanks to these 2 methods.

In addition to everything else, I used multithreading to smoothly fade out the main menu music when the game starts, because I noticed it was stopping abruptly. I used std::thread, std::join, and std::this_thread::sleep_for(std::chrono::milliseconds()) along with multiple threads to manage the fade-out effect.

//Switch Case

if (mouseState == LEFT_MOUSE_BUTTON && menuStart->IsMouseHovering(mouseX, mouseY))
{

    std::thread t1 (DestroyMainMenu);

    std::this_thread::sleep_for(std::chrono::milliseconds(500));

    if (t1.joinable())
    {
        t1.join();
    }

    break;
}

// Destroy main menu elements and fade out music

void Game::DestroyMainMenu()
{
    currentGameState = GAMEPLAY;
    TTF_CloseFont(titleFont);
    TTF_CloseFont(menuFont);
    delete(menuTitle);
    menuTitle = nullptr;
    delete(menuStart);
    menuStart = nullptr;
    delete(menuContinue);
    menuContinue = nullptr;
    delete(menuExit);
    menuExit = nullptr;
    menuFontsLoaded = false;
    haveElementsLoaded = false;

    std::thread t2(menuMusic->StopAudio, 500);

    std::this_thread::sleep_for(std::chrono::milliseconds(500));

    if (t2.joinable())
    {
        t2.join();
    }

    menuMusic->plays = false;    
}

The main thread pauses for 500 milliseconds while the t1 thread runs the StopAudio method on another thread named t2. Then, t1 waits another 500 milliseconds to allow the fade-out effect to finish. Once t2 completes the operation, it joins t1, and then t1 joins the main thread, allowing the game loop to proceed normally.