SFML community forums

Help => System => Topic started by: Aiden_Cohen on April 03, 2018, 10:18:11 pm

Title: How to run a function until an event happens
Post by: Aiden_Cohen on April 03, 2018, 10:18:11 pm
I'm creating a game, where I'm drawing a main menu, however, when I try and clear the screen in the function that draws the main menu, it just gets redrawn by the game loop. I also can't draw it only once, as my main menu has some gui animations that I want to keep. So how would i redraw the main menu over and over until the user clicks on one of the buttons.

Here is my code

main.cpp
#include <SFML/Graphics.hpp>
#include <iostream>
#include "write.h"
#include <SFML/Graphics/Font.hpp>
#include "menu.h"
int main()
{
sf::RenderWindow windows(sf::VideoMode::getDesktopMode(), "SFML works!",sf::Style::None);
sf::Font fonts;

if(!fonts.loadFromFile("assets/bit.ttf"))
{

std::cerr << "Error loading font" << std::endl;
}


    while (windows.isOpen())
    {
        sf::Event event;
        while (windows.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
            {
                windows.close();
            }
            if(event.type == sf::Event::KeyPressed)
            {
            if(event.key.code == sf::Keyboard::Escape)
            {
             
                 windows.close();
            }
            }
            if(event.type == sf::Event::MouseMoved)
            {


            }
           
        }
     
       
       
       

         buildMenu(fonts,windows);

       
       
   

    }

    return 0;
}

menu.cpp
#include <SFML/Graphics.hpp>
#include <iostream>
#include "write.h"
#include <SFML/Graphics/Font.hpp>
#include "menu.h"
void buildMenu(sf::Font font, sf::RenderWindow& window)
{


sf::Color dgreen(0x54ff9fff);
sf::Color green(0x240fe2ff);
sf::Color bluegreen(0x00e64dff);
sf::Color red(0xff3436ff);
sf::Color cyan(0x1b990dff);
sf::RectangleShape rectangle2;
rectangle2.setSize(sf::Vector2f(850, 130));
rectangle2.setOutlineColor(dgreen);
rectangle2.setOutlineThickness(10);
rectangle2.setPosition(10, 740 );
rectangle2.setFillColor(sf::Color::Transparent);
sf::RectangleShape rectangle1;
rectangle1.setSize(sf::Vector2f(850, 130));
rectangle1.setOutlineColor(dgreen);
rectangle1.setOutlineThickness(10);
rectangle1.setPosition(10, 540 );
rectangle1.setFillColor(sf::Color::Transparent);
sf::RectangleShape rectangle;
rectangle.setSize(sf::Vector2f(850, 130));
rectangle.setOutlineColor(dgreen);
rectangle.setOutlineThickness(10);
rectangle.setPosition(10, 340 );
rectangle.setFillColor(sf::Color::Transparent);
sf::Vector2i mousepos = sf::Mouse::getPosition();
float x = mousepos.x;
float y = mousepos.y;

if(((850 > x) && (x > 10)) && ((470> y) && (y > 340)))
{

rectangle.setOutlineColor(red);

}

if(((850 > x) && (x > 10)) && ((670> y) && (y > 500)))
{

rectangle1.setOutlineColor(cyan);

}

if(((850 > x) && (x > 10)) && ((870> y) && (y > 700)))
{

rectangle2.setOutlineColor(green);

}



if((((850 > x) && (x > 10)) && ((870> y) && (y > 700)))&& (sf::Mouse::isButtonPressed(sf::Mouse::Left)))
{

window.clear();
window.display();
}
if((((850 > x) && (x > 10)) && ((670> y) && (y > 500)))&& (sf::Mouse::isButtonPressed(sf::Mouse::Left)))
{

window.clear();
window.display();
}
if((((850 > x) && (x > 10)) && ((470> y) && (y > 300)))&& (sf::Mouse::isButtonPressed(sf::Mouse::Left)))
{

window.clear();
window.display();
}


window.clear();
window.draw(print("Snake++", font,250,0,0, bluegreen));
window.draw(print("Play Game",font,150,25,300,bluegreen));
window.draw(print("Settings",font,150,25,500,bluegreen));
window.draw(print("Exit",font,150,25,700,bluegreen));
window.draw(rectangle);
window.draw(rectangle1);
window.draw(rectangle2);
window.display();

}
Title: Re: How to run a function until an event happens
Post by: AlexAUT on April 03, 2018, 11:39:06 pm
Keep in mind that there are infinite ways of achieving this, so my suggestion below is just one possibility.

Try to separate initial state, update logic and rendering. Therefore initialize your GUI once (in some init function or constructor of a class...). Then have an update function which will do some fancy animations and than have one render function which draws the current state of GUI.

So you call the init function before the game loop and then call update and render in every frame. This of course does not solve your problem, but now you can use a state machine to switch between different states very easily.
There are a lot of well written tutorial about them, I personally like this one (https://gamedevelopment.tutsplus.com/tutorials/finite-state-machines-theory-and-implementation--gamedev-11867). State machines are really handy for all different kind of problems you will encounter in the future, so invest some time in them it won't be wasted  ;).


AlexAUT
Title: Re: How to run a function until an event happens
Post by: Hapax on April 04, 2018, 12:20:17 am
Although this isn't necessarily related to your question, you should note that when you pass the font to "build menu", it passes by value (copies the entire resource every time this function is called). You more than likely want to pass resources (expensive ones like fonts, textures and sound buffers) by reference (sf::Font& font), preferably, or by pointer (sf::Font* font) if absolutely necessary.