Day 51/100 100 Days of Code

Day 51/100 100 Days of Code

Rebuild Back Better

The menu element structure now works. It helped me remove over 150 lines of code as there is much less repeating code. The structure now creates menu elements and changes the element's color when it is hovered by the mouse cursor. The game exits when the user presses the left mouse button when the Exit option is activated.

There are 2 issues that I need to solve:

  1. The option type enumerator has been created twice because I have to input the option being created.

  2. The enumerator is not expandable. I wonder if I can use templates with enumerators.

    Menu Element Struct

template<typename S, typename T, typename C, typename F, typename R>
struct MenuElement
{
    enum ElementType
    {
        TITLE = 0,
        CONTINUE,
        START,
        EXIT
    };

    float x, y;
    int currentState;
    float width, height;
    std::string content;
    F *font;
    R *renderer;
    C notHovered = {0xbb, 0xbb, 0xbb};
    C disabledOption = {0xAA, 0xAA, 0xAA};
    C hoverOption = {0xE0, 0xAA, 0x95};
    C titleColor = {0xE0, 0xAA, 0x95};

    MenuElement(float inputX, float inputY, F *inputFont, R *inputRender);
    void CreateOption(std::string content, float getMouseX, float getMouseY, int elementType);
    bool IsMouseHovering(float inputMouseX, float inputMouseY);
};

The Load Menu Method

This is where I cut all those lines of code. The method is much smaller now.

void Game::LoadMainMenu()
{
    // Add Title
    menuTitle->CreateOption("Rebuild Back Better", mouseX, mouseY, TITLE);    
    menuContinue->CreateOption("Continue", mouseX, mouseY, CONTINUE);
    menuStart->CreateOption("Start", mouseX, mouseY, START);
    menuExit->CreateOption("Exit", mouseX, mouseY, EXIT);            
}

Menu Element Create

The create option element can now create each option and set the correct color to the option's font when the mouse cursor hovers it. The IsMouseHovering is a structure method.

template<>
void MenuElement<SDL_Surface, SDL_Texture, SDL_Color, TTF_Font, SDL_Renderer>::CreateOption(std::string content, 
                                                                                            float getMouseX, 
                                                                                            float getMouseY, 
                                                                                            int elementType)
{
    SDL_Color fontColor;

    switch(elementType)
    {
        case TITLE:
            fontColor = titleColor;
            break;

        case CONTINUE:
            fontColor = disabledOption;
            break;

        case START:
            if (IsMouseHovering(getMouseX, getMouseY))
            {
                fontColor = hoverOption;
            }else
            {
                fontColor = notHovered;
            }
            break;

        case EXIT:
            if (IsMouseHovering(getMouseX, getMouseY))
            {
                fontColor = hoverOption;
            }else
            {
                fontColor = notHovered;
            }
            break;
    }
    SDL_Surface *optionSurface = TTF_RenderText_Solid(font,
                                            content.c_str(),
                                            fontColor);
    if (optionSurface == nullptr)
    {
        std::cout << "Failed to create option surface ";
        std::cout << SDL_GetError() << std::endl;
        exit(-1);
    }

    SDL_Texture *optionTexture = SDL_CreateTextureFromSurface(renderer, optionSurface);

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

    width = optionSurface->w;
    height = optionSurface->h;

    const SDL_FRect optionHolder = {x, y, 
                                    static_cast<float>(optionSurface->w), 
                                    static_cast<float>(optionSurface->h)};     

    SDL_RenderTexture(renderer, optionTexture, nullptr, &optionHolder);        

    SDL_DestroySurface(optionSurface);
    optionSurface = nullptr;
    SDL_DestroyTexture(optionTexture);
    optionTexture = nullptr;    
}

IsMouseHovering Method

The method is used to check if the mouse is within the boundaries of an option.

template<>
bool MenuElement<SDL_Surface, SDL_Texture, SDL_Color, TTF_Font, SDL_Renderer>::IsMouseHovering(float inputMouseX, float inputMouseY)
{
    if (inputMouseX >= x && inputMouseX <= x + width)
    {
        if (inputMouseY >= y && inputMouseY <= y + height)
        {
            return true;
        }
    }

    return false;
}

Interactivity

The game now exists when the exit button is pressed with the following code:

if (mouseState == LEFT_MOUSE_BUTTON && menuExit->IsMouseHovering(mouseX, mouseY))
    {
        quit = true;    
    }

It was quite a productive day and I learned a lot about building structures, remembered how to use templates, and how to expand their features.