SFML community forums

Help => General => Topic started by: Josh LL on August 22, 2019, 08:18:28 pm

Title: Need help with keeping an process going even after a key has been pressed
Post by: Josh LL on August 22, 2019, 08:18:28 pm
Hello!!

I'm quite new to SFML and C++ but please bear with me lol.

So I'm making a super simple game where you have to guide a spaceship through astroids, but I want to implement a pause feature once a key has been pressed. My problem is I can only get it to work WHILE I hold the key down and I want it so it pauses once I press and release the key, and then unpause when I press and release the key again, just like how normal pause buttons in real games work.

Not sure if this works or not but it would be great if it is possible to do this.

Thanks!!!
Josh LL
Title: Re: Need help with keeping an process going even after a key has been pressed
Post by: Geheim on August 22, 2019, 10:16:38 pm
One way to do this is to simply toggle a boolean flag when you press/release your pause key and only update your game logic if the flag is set.
Title: Re: Need help with keeping an process going even after a key has been pressed
Post by: Josh LL on August 23, 2019, 12:09:13 am
I have tried this but as soon as i de-press the key it instantly turns the boolean value back so I still have the same problem
Title: Re: Need help with keeping an process going even after a key has been pressed
Post by: G. on August 23, 2019, 02:04:49 am
?
Use a boolean. Simply invert its value on your key press event (or release).
Title: Re: Need help with keeping an process going even after a key has been pressed
Post by: nogoodname on August 23, 2019, 02:38:22 am
I have tried this but as soon as i de-press the key it instantly turns the boolean value back so I still have the same problem

It would be nice to show your code, so one could see what you're trying to do. My guess is that you're using the sf::Keyboard::isKeyPressed function. Instead you should try to use events.

Here's one example. (This should be in the switch statement in your event loop.)
case sf::Event::KeyReleased:
    if(event.key.code == sf::Keyboard::Escape) //Assuming that the pause button is escape.
        isPaused ^= 1;   //isPaused is the boolean flag, the ^=1 flips the value
break;
 

Title: Re: Need help with keeping an process going even after a key has been pressed
Post by: Josh LL on August 23, 2019, 04:49:46 pm
OMGOSH it actually works thanks soo much. now I actually used a while statement instead of switch cause I actually don't have any switch statements in my game. I hope this isn't a bad thing?? Here is my code if u want to check it out.

#include <iostream>
#include <SFML/Audio.hpp>
#include <SFML/Graphics.hpp>
#include <string>
#include <sstream>
using namespace sf;
using namespace std;


int main(){
    Clock clock;
    clock.restart();
   
   
    RenderWindow window(sf::VideoMode(1000, 1000), "My window");
    window.setTitle("SFML window");
   
    window.setFramerateLimit(60);
   
    FloatRect SwindowBounds({49.f, 0.f},{955.f, 970.f} );
   
    FloatRect AwindowBounds({0.f, 0.f},{1000.f, 1000.f} );
   
    Text text;
   
    Font font;
    if (!font.loadFromFile("sansation.ttf")){
        return EXIT_FAILURE;
    }
    text.setCharacterSize(100);
    text.setFillColor(sf::Color::Black);
    text.setString("five");
    text.setFont(font);
    text.setStyle(sf::Text::Bold | sf::Text::Underlined);
   
    Texture backGround;
    if(!backGround.loadFromFile("2616074.jpg")){
        return EXIT_FAILURE;
    }
    Sprite BG(backGround);
   
    CircleShape triangle(80.f, 3);
   
    Texture Astroid;
    if(!Astroid.loadFromFile("Astroid.png")){
        return EXIT_FAILURE;
    }
    Sprite sprite1(Astroid);
   
    Sprite sprite2(Astroid);
   
    Sprite sprite3(Astroid);
   
    Sprite sprite4(Astroid);
   
    Sprite sprite5(Astroid);
   
    BG.setScale(.7, .7);
   
    triangle.setPosition(425, 625);
   
    triangle.setScale(.4, .4);
   
    sprite1.setPosition(700, -50);
   
    sprite1.setScale(.15, .15);
   
    sprite2.setPosition(500, -50);
   
    sprite2.setScale(.17, .17);
   
    sprite3.setPosition(300, -50);
   
    sprite3.setScale(.12, .12);
   
    sprite4.setPosition(600, -50);
   
    sprite4.setScale(.18, .18);
   
    sprite5.setPosition(400, -50);
   
    sprite5.setScale(.15, .15);
   
   
    while (window.isOpen())
    {
        Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed){
                    window.close();
            }
           
    }
        //here is how I paused it
        bool isPaused = false;
        while(sf::Event::KeyReleased){
            if(event.key.code == sf::Keyboard::Escape)
                isPaused = true;
        break;
        }
        if (!isPaused) {
       
       
        window.clear(Color::White);
       
        window.draw(BG);
       
        Time elapsed = clock.getElapsedTime();
        int sec = elapsed.asSeconds();
        cout << sec << endl;
        if(sec >= 2){
            window.draw(sprite1);
            sprite1.move(0.0f,8.0f);
        }
        if(sec >= 5){
            window.draw(sprite2);
            sprite2.move(0.0f,7.0f);
        }
        if(sec >= 10){
            window.draw(sprite3);
            sprite3.move(0.0f,8.0f);
        }
        if(sec >= 15){
            window.draw(sprite4);
            sprite4.move(0.0f,9.0f);
        }
        if(sec >= 20){
            window.draw(sprite5);
            sprite5.move(0.0f,6.0f);
        }
       
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left)){
            triangle.move(Vector2f(-15.f, 0.f));
        }
       
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right)){
            triangle.move(Vector2f(15.f, 0.f));
        }
       
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up)){
            triangle.move(Vector2f(0.f, -15.f));
        }
       
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down)){
            triangle.move(Vector2f(0.f, 15.f));
        }
       
        FloatRect shipBox = triangle.getGlobalBounds();
       
        FloatRect astroidBox1 = sprite1.getGlobalBounds();
       
        FloatRect astroidBox2 = sprite2.getGlobalBounds();
       
        FloatRect astroidBox3 = sprite3.getGlobalBounds();
       
        FloatRect astroidBox4 = sprite4.getGlobalBounds();
       
        FloatRect astroidBox5 = sprite5.getGlobalBounds();
       
        if (!shipBox.intersects(SwindowBounds))
        {
            window.close();
        }
        if (shipBox.intersects(astroidBox1))
        {
            window.close();
        }
        if (shipBox.intersects(astroidBox2))
        {
            window.close();
        }
        if (shipBox.intersects(astroidBox3))
        {
            window.close();
        }
        if (shipBox.intersects(astroidBox4))
        {
            window.close();
        }
        if (shipBox.intersects(astroidBox5))
        {
            window.close();
        }
        if (!astroidBox1.intersects(AwindowBounds))
        {
            sprite1.setPosition(rand()%1000-1,-50);
        }
        if (!astroidBox2.intersects(AwindowBounds))
        {
            sprite2.setPosition(rand()%1000-1,-50);
        }
        if (!astroidBox3.intersects(AwindowBounds))
        {
            sprite3.setPosition(rand()%1000-1,-50);
        }
        if (!astroidBox4.intersects(AwindowBounds))
        {
            sprite4.setPosition(rand()%1000-1,-50);
        }
        if (!astroidBox5.intersects(AwindowBounds))
        {
            sprite5.setPosition(rand()%1000-1,-50);
        }
       
       
        window.draw(triangle);
       
        window.display();}
}
}

 
Title: Re: Need help with keeping an process going even after a key has been pressed
Post by: nogoodname on August 24, 2019, 03:02:52 am
I'm not sure if the forum's formatting messed up your code, because your brace placement is very out of place and misleading.

(click to show/hide)

Now lets look at a bit of your code.
//here is how I paused it
while(sf::Event::KeyReleased)
{
        if(event.key.code == sf::Keyboard::Escape)
            isPaused = true;
        break;
}
 
There's a few bits of redundancy here that makes the code misleading, I will go over them one by one.

(click to show/hide)

Let's go over the main issue. Looking at the code again (with our simplifications, and at a slightly bigger scope).
Event event;
while (window.pollEvent(event))
{
    if (event.type == sf::Event::Closed){
            window.close();
    }
   
}

//here is how I paused it
bool isPaused = false;
if(event.key.code == sf::Keyboard::Escape)
    isPaused = true;
 
There's an issue here, you are trying to evaluate event.key.code without checking for the correct event.
sf::Event is a union which can only have one valid type. If you try to evaluate an invalid event, you are invoking undefined behaviour (which is never good). So how would we fix this? But checking for the correct event before evaluating it. This should be done in the event loop.
Here's the fixed version:
bool isPaused = false;
while (window.isOpen())
{
    Event event;
    while (window.pollEvent(event))    //this is the event loop
    {
        if(event.type == Event::Closed)
                window.close();
        else if(event.type == Event::KeyReleased) {
                if(event.key.code == sf::Keyboard::Escape)
                        isPaused = !isPaused;
        }
    }
//...
 
As you can see the if(event.type == Event::[Insert Event Name Here]] ) checks the event type, this makes sure that you're not evaluating an invalid event. And like I said this should be done in the event loop.


Here's a simple complete test code as an example, to illustrate my point and to show that it works.
#include <iostream>
#include <SFML/Window.hpp>

int main(){
    sf::Window window(sf::VideoMode(128,128), "Test");
    bool isPaused = false;
    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))    //this is the event loop
        {
            if(event.type == sf::Event::Closed)
                    window.close();
            else if(event.type == sf::Event::KeyReleased) {
                    if(event.key.code == sf::Keyboard::Escape)
                            isPaused = !isPaused;
            }
        }

        if (!isPaused)
            std::cout<<"NOT ";

        std::cout<<"paused\n";
    }
    return 0;
}
 

 If you haven't already, I would recommend reading the official guide on events.  (https://www.sfml-dev.org/tutorials/2.5/window-events.php)
Title: Re: Need help with keeping an process going even after a key has been pressed
Post by: Josh LL on August 26, 2019, 02:49:46 pm
Thank you sooo much for pointing these things out I really really appreciate it :) :).
I do have one question tho why is it so important to have the keypressed event in the event loop cause it totally works in where I had it. will it cause problems later on?? or is it just good practice to do so?
Title: Re: Need help with keeping an process going even after a key has been pressed
Post by: nogoodname on August 26, 2019, 05:15:40 pm
Thank you sooo much for pointing these things out I really really appreciate it :) :).
I do have one question tho why is it so important to have the keypressed event in the event loop cause it totally works in where I had it. will it cause problems later on?? or is it just good practice to do so?

Checking for events outside of the event loop means that you will only check for the last event per frame. This can cause issue, for example if you press the pause button and move the mouse at the same time, there will be 2 events: a KeyBoard event and a Mouse event, however your code will only check for only 1 event, so sometimes if you press pause, it would not pause.

By checking for events in the event loop, you will check for all the events rather than just one, so it will always work.
Title: Re: Need help with keeping an process going even after a key has been pressed
Post by: Josh LL on August 26, 2019, 11:04:38 pm
Ohhhh that makes soo much sense cause I noticed if I moved my mouse while the game was paused it would un-pause and I wasn't sure why. Thank you soooo so much!!
Title: Re: Need help with keeping an process going even after a key has been pressed
Post by: Josh LL on August 26, 2019, 11:36:16 pm
now how do I get it to un-pause.... crap....
Title: Re: Need help with keeping an process going even after a key has been pressed
Post by: Josh LL on August 27, 2019, 12:13:10 am
OHHH I figured it out nvm thanks soo much everyone!!! (especially nogoodname!)