Advertisement

[SFML] Menu system not working properly

Started by January 04, 2016 12:26 PM
1 comment, last by louie999 8 years, 11 months ago

So I was trying to make a menu system for the game I'm making, it was almost good, until I discovered this annoying problem.


#include <iostream>
#include <vector>
#include <memory>
#include <string>
#include <functional>
#include <SFML/Graphics.hpp>
#include "menuhandler.hpp"

const int _WIDTH_ = 800;
const int _HEIGHT_ = 600;

int main()
{
    sf::RenderWindow Main_Window(sf::VideoMode(_WIDTH_, _HEIGHT_), "Total War");
    Gui::FontLoader fontLoader;
    fontLoader.loadFont("FREESCPT.TTF");

    Gui::GameState mainMenu("MainMenu");
    Gui::Button* bPlay = Gui::Button::New(mainMenu, 15.f, 100.f, 50, 20, "Play", fontLoader.font, 30);
    Gui::Button* bQuit = Gui::Button::New(mainMenu, 15.f, 200.f, 50, 20, "Quit", fontLoader.font, 30);

    while (Main_Window.isOpen())
    {
        sf::Event event;
        while (Main_Window.pollEvent(event))
        {
            switch (event.type)
            {
                case sf::Event::Closed:
                    Main_Window.close();
                    break;
                default:
                    break;
            }
        }
        Gui::Event evn;
        while (Gui::Base::checkEvent(Main_Window, evn))
        {
            if (evn.type == Gui::Event::EVENT::MOUSE_ENTER)
            {
                if (evn.object == bPlay)
                {
                    std::cout << "Mouse is in play button!";
                }
                if (evn.object == bQuit)
                {
                    std::cout << "Mouse is in quit button!";
                }
            }
        }
        Main_Window.clear(sf::Color(0, 200, 200, 150));
        Gui::Base::drawGUI(Main_Window);
        Main_Window.display();
    }
}

It properly displays those buttons(bPlay and bQuit) it also displays the message when the mouse is on bPlay button but it doesn't display the message when it's on the bQuit button, it only seems to pay attention to the first button created(in this case it's bPlay). I have no idea what caused this problem o.O here's the rest of my code:(menuhandler.hpp and menuhandler.cpp)


#pragma once
#include "gamestate.hpp"

namespace Gui
{
    class FontLoader
    {
        public:
            sf::Font font;

            FontLoader();
            bool loadFont(sf::String filepath);
    };

    class Base;
    class Button;

    class Event
    {
        public:
            Base* object;
            enum EVENT {NO_EVENT, MOUSE_ENTER, MOUSE_CLICKED};
            EVENT type = NO_EVENT;
            Event();
            bool operator==(Gui::Button& button);
    };

    class Base
    {
        public:
            static std::vector<std::unique_ptr<Base>> container;
            float PosX;
            float PosY;
            float Width;
            float Height;
            sf::String Text;
            sf::Font Font;
            unsigned int TextSize;
            Gui::GameState State;
            sf::IntRect MouseArea;
            sf::Text TextDisplay;
            sf::Sprite SprDisplay;
            bool show = true;

            Base();
            bool isMouseIn(sf::RenderWindow &win);
            bool isClicked(sf::RenderWindow &win);
            static bool checkEvent(sf::RenderWindow& win, Event& event);
            static void drawGUI(sf::RenderWindow& win);
            void setPos(float newX, float newY);
            void setWidth(float newWidth);
            void setHeight(float newHeight);
            void setShow(bool b);
    };

    class Button : public Base
    {
        public:
            Button(Gui::GameState& gameState, float x, float y, float width, float height, sf::String text, sf::Font& font, unsigned int textSize);
            static Button* New(Gui::GameState& gameState, float x, float y, float width, float height, sf::String text, sf::Font& font, unsigned int textSize);
    };
}


#include <SFML/Graphics.hpp>
#include <stdarg.h>
#include <vector>
#include <memory>
#include <functional>
#include <iostream>
#include "menuhandler.hpp"

bool Gui::Event::operator==(Gui::Button& button)
{
    if (*this == button)
    {
        return true;
    }
    return false;
}

Gui::FontLoader::FontLoader() {}

bool Gui::FontLoader::loadFont(sf::String filepath)
{
    if (!font.loadFromFile("Art/Fonts/" + filepath))
    {
        return false;
    }
    else
        return true;
}

std::vector<std::unique_ptr<Gui::Base>> Gui::Base::container;

Gui::Event::Event() {}

Gui::Base::Base() {}

bool Gui::Base::isMouseIn(sf::RenderWindow &win)
{
    sf::Vector2i mCoords = sf::Mouse::getPosition(win);
    auto w = this->PosX + this->Width;
    auto h = this->PosY + this->Height;

    if (mCoords.x >= this->PosX and mCoords.y >= this->PosY and mCoords.x <= w and mCoords.y <= h)
    {
        return true;
    }
    else
    {
        return false;
    }
}

bool Gui::Base::isClicked(sf::RenderWindow &win)
{
    if (this->isMouseIn(win) and sf::Mouse::isButtonPressed(sf::Mouse::Left))
    {
        return true;
    }
    return false;
}

bool Gui::Base::checkEvent(sf::RenderWindow &win, Event &event)
{
    for (auto &gui: container)
    {
        event.object = nullptr;
        event.type = Gui::Event::EVENT::NO_EVENT;
        if (gui->isMouseIn(win))
        {
            event.object = gui.get();
            event.type = Gui::Event::MOUSE_ENTER;
            return true;
        }
        if (gui->isClicked(win))
        {
            event.object = gui.get();
            event.type = Gui::Event::MOUSE_CLICKED;
            return true;
        }
        return false;
    }
    return false;
}

void Gui::Base::drawGUI(sf::RenderWindow& win)
{
    for (auto &gui: container)
    {
        if (gui->show)
            win.draw(gui->TextDisplay);
    }
}

void Gui::Base::setShow(bool b)
{
    this->show = b;
}

Gui::Button::Button(Gui::GameState& gameState, float x, float y, float width, float height, sf::String text, sf::Font& font, unsigned int textSize)
{
    State = gameState;
    PosX = x;
    PosY = y;
    Width = width;
    Height = height;
    Text = text;
    Font = font;
    TextSize = textSize;
    TextDisplay.setString(Text);
    TextDisplay.setFont(Font);
    TextDisplay.setCharacterSize(TextSize);
    TextDisplay.setPosition(PosX, PosY);
}

Gui::Button* Gui::Button::New(Gui::GameState& gameState, float x, float y, float width, float height, sf::String text, sf::Font& font, unsigned int textSize)
{
    auto *newObj = new Gui::Button(gameState, x, y, width, height, text, font, textSize);
    Gui::Base::container.push_back(std::unique_ptr<Gui::Button>(newObj));
    std::cout << "Created object with address of: " << newObj << std::endl;
    return newObj;
}

Thanks in advance :S

Make sure to flush the cout stream object to make sure that you can see what has been written.

std::cout << "Mouse is in quit button!" << std::flush;

If you use std::endl you don't need to use std::flush because it will flush automatically.

I think the real problem is that you return at the end of the loop in checkEvent.
Advertisement

Make sure to flush the cout stream object to make sure that you can see what has been written.


std::cout << "Mouse is in quit button!" << std::flush;
If you use std::endl you don't need to use std::flush because it will flush automatically.

I think the real problem is that you return at the end of the loop in checkEvent.

Thanks dude :D, I removed that "return false" inside the loop and it works properly :D

This topic is closed to new replies.

Advertisement