Coding a main menu

This week has been a bit hectic. Lots to do and little time to do it. We’ve had some big features that feel absolutely necessary to implement for the final version of the game. One of those was a main menu from where the player can start the game and look at highscores, credits, and the control scheme. (And quit the application of course. This was a bit of a hassle to achieve, and the solution isn’t even very pretty. More about that later. Actually, probably not.) The different buttons in the menu are instances of the same class, GUIButton, separated by an Enum parameter. Their features include:

  • Clicked using the mouse, which triggers different functions depending on the kind of button
  • Changing the image when the cursor is on top of the button
  • Hiding the button and making it non-clickable if the player is currently in a sub menu where the button is not supposed to be shown

Since there are only two layers in the menu: the main screen, and the other screens, all that’s needed to navigate back to the main screen is a back button which always sends the player back to the main screen, regardless of which sub menu it’s in.

The system seems simple enough, but the getting all the logic right took me some time. The worst part is the clicking, because since we haven’t used a clever way to manage inputs, all we know is whether the mouse button is pressed or not. Only getting the code to perform only one menu button click when the mouse button is held means we need another member variable to store a boolean whether the button has been let go of or not between ticks. The system as it turned out is not perfect, with the main issue being that a button is clicked if the cursor is moved to the GUI button while the mouse button is held. But I figured it’s not big enough a problem to spend more time on the code. Included below is the complete Update() method from the MenuState class. I think it’s rather self-explanatory, and I included some comments to possibly clarify some things. The Draw() function is not very interesting, it basically just checks what sub menu the player is in, and draws different backgrounds, and then it checks which buttons are visible and draws those. I was going to add a screenshot of the menu, but for some reason my screenshots have started to capture Visual Studio and the Console window instead of the game screen; so here’s a picture of a fish instead. He is not amused.

Since made by one of our artists as a placeholder for the highscore screen, it’s actually perfectly related to the rest of the post.

 

bool MenuState::Update(float deltatime)
<pre>{
    // This stuff is to make the mouse button perform only one click when held
    if (!sf::Mouse::isButtonPressed(sf::Mouse::Left))
        m_mousePressed = false;

    // Set button border to NOT show
    for (int i = 0; i < m_buttons.size(); i++)
    {
        m_buttons[i]->SetHover(false);
    }

    for (int i = 0; i < m_buttons.size(); i++)
    {
        int buttonX = m_buttons[i]->GetPosition().x;
        int buttonY = m_buttons[i]->GetPosition().y;
        int buttonWidth = m_buttons[i]->GetWidth();
        int buttonHeight = m_buttons[i]->GetHeight();
        int mouseX = sf::Mouse::getPosition().x;
        int mouseY = sf::Mouse::getPosition().y;
        ETYPE buttonType = m_buttons[i]->GetType();

        if (!m_buttons[i]->GetHidden())
        {
            
            if (mouseX >= buttonX && mouseX <= (buttonX + buttonWidth) && mouseY >= buttonY && mouseY <= (buttonY + buttonHeight)) // Horizontal and vertical
            {
                m_buttons[i]->SetHover(true);
                if (sf::Mouse::isButtonPressed(sf::Mouse::Left) == true && m_mousePressed == false)
                {
                    if (buttonType == START)
                    {
                        m_mousePressed = true;
                        return false; // Go to next State, which is the GameState
                    }

                    else if (buttonType == HIGHSCORE)
                    {
                        m_subMenu = HIGHSCORE_SCREEN;
                        for (int i = 0; i < 4; i++)
                        {
                            m_buttons[i]->SetHidden(true);
                        }
                        m_buttons[4]->SetHidden(false);
                        m_mousePressed = true;
                        return true;
                    }

                    else if (buttonType == CREDITS)
                    {
                        m_subMenu = CREDITS_SCREEN;
                        for (int i = 0; i < 4; i++)
                        {
                            m_buttons[i]->SetHidden(true);
                        }
                        m_buttons[4]->SetHidden(false);
                        m_mousePressed = true;
                        return true;
                    }

                    else if (buttonType == QUIT)
                    {
                        m_shutdown = true; // Will break the game loop in Engine
                    }

                    else if (buttonType == BACK)
                    {
                        m_subMenu = MAIN_SCREEN;
                        for (int i = 0; i < 4; i++)
                        {
                            m_buttons[i]->SetHidden(false);
                        }
                        m_buttons[4]->SetHidden(true);
                        m_mousePressed = true;
                        return true;
                    }
                }
                return true;

            }
        }
    }

    return true;
}
Advertisements

One thought on “Coding a main menu

  1. Hey man!

    Hopefully this week has been less stressful for you and that you have had time to implement all the things you guys wanted! Interesting choice of how your menu works since you have layers added onto the initial background image rather than switching to another state where you handle the different events. And if you have manged to get it working correctly it will be a better solution rather than having different states and changing back and forth, it´s going to be interesting to see it in action!

    I can see how the use of a boolean is appropriate here since you still have the original buttons visible but transparent(?) while you are in a sub menu and depending of the bool the button should be clicked or not. A screenshot of the main menu in-game would have helped some and it is unfortunate that you are currently having problem capturing a screenshot. 

    I have however some questions regarding why you decided to go with layers and not using different states to handle your options and how you solved the use of different layers rather than how the buttons works. But that is only my opinion and apart from this it was a well written post if a bit clustered but I could still follow your trail of thought. Looking forward to see this on Friday!

    Keep up the good work!

    //Feedback from David Eliasson, Group 10, 5SD033, GAME

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s