Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Need help with keeping an process going even after a key has been pressed  (Read 4897 times)

0 Members and 2 Guests are viewing this topic.

Josh LL

  • Newbie
  • *
  • Posts: 7
    • View Profile
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

Geheim

  • Full Member
  • ***
  • Posts: 201
    • View Profile
    • Email
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.
Failing to succeed does not mean failing to progress!

Josh LL

  • Newbie
  • *
  • Posts: 7
    • View Profile
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

G.

  • Hero Member
  • *****
  • Posts: 1593
    • View Profile
?
Use a boolean. Simply invert its value on your key press event (or release).

nogoodname

  • Newbie
  • *
  • Posts: 21
    • View Profile
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;
 

« Last Edit: August 24, 2019, 02:19:41 am by nogoodname »

Josh LL

  • Newbie
  • *
  • Posts: 7
    • View Profile
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();}
}
}

 

nogoodname

  • Newbie
  • *
  • Posts: 21
    • View Profile
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.
« Last Edit: August 24, 2019, 03:41:05 am by nogoodname »

Josh LL

  • Newbie
  • *
  • Posts: 7
    • View Profile
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?

nogoodname

  • Newbie
  • *
  • Posts: 21
    • View Profile
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.

Josh LL

  • Newbie
  • *
  • Posts: 7
    • View Profile
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!!

Josh LL

  • Newbie
  • *
  • Posts: 7
    • View Profile
now how do I get it to un-pause.... crap....

Josh LL

  • Newbie
  • *
  • Posts: 7
    • View Profile
OHHH I figured it out nvm thanks soo much everyone!!! (especially nogoodname!)