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

Author Topic: How to only get one input per key press during a loop?  (Read 12948 times)

0 Members and 1 Guest are viewing this topic.

wh1t3crayon

  • Jr. Member
  • **
  • Posts: 93
    • View Profile
How to only get one input per key press during a loop?
« on: September 18, 2014, 02:27:36 pm »
So I want a game piece to only move one square at a time when an arrow key is pressed, but the game loop is checking for if they key is pressed way too quickly and the piece moves between 5 and 7 pieces if I press the arrow key really quickly. Here is the code
void Engine::Go(){
        while(window.isOpen()){
                if(timeElapsed.asSeconds() >= 100){
                        timeElapsed = clock.restart();
                }
                ProcessInput();
                UpdateCPU();
                Render();
                timeElapsed += clock.getElapsedTime();
        }
}

void Engine::ProcessInput(){
        while(window.pollEvent(event)){
                if(event.type == (sf::Event::Closed))
                        window.close();
        }
        //process movement detection of piece
       
                int temp = level.GetGamePieces().size();
                if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left)){
                        level.GetGamePieces().at(temp - 1).GetPieceSprite().move(-10, 0);
                        std::cout << "left";
                       
                }
                else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right)){
                        level.GetGamePieces().at(temp - 1).GetPieceSprite().move(10,0);
                        std::cout << "right";
                       
                }
                else{
                        level.GetGamePieces().at(temp - 1).GetPieceSprite().move(0,10);
                        std::cout << "down";
               
        }
}

So the code is moving the piece more than once when they key is pressed. How would I get the piece to move only once when the key is pressed?

Strelok

  • Full Member
  • ***
  • Posts: 139
    • View Profile
    • GitHub
Re: How to only get one input per key press during a loop?
« Reply #1 on: September 18, 2014, 02:30:35 pm »
Use the keypressevent instead of polling the os for the state of the key so that the key press will happen only once

wh1t3crayon

  • Jr. Member
  • **
  • Posts: 93
    • View Profile
Re: How to only get one input per key press during a loop?
« Reply #2 on: September 18, 2014, 02:40:01 pm »
Quote
Use the keypressevent instead of polling the os for the state of the key so that the key press will happen only once

How do I use that code though? Here is what I have
if(event.type == (sf::Event::KeyPressed)){
                        switch(event.type){
                                case //left arrow key is pressed
                        }
                }
But what goes in the commented section to get the key pressed event? Also, is this what you meant?

Strelok

  • Full Member
  • ***
  • Posts: 139
    • View Profile
    • GitHub
Re: How to only get one input per key press during a loop?
« Reply #3 on: September 18, 2014, 02:42:25 pm »

wh1t3crayon

  • Jr. Member
  • **
  • Posts: 93
    • View Profile
Re: How to only get one input per key press during a loop?
« Reply #4 on: September 18, 2014, 02:50:58 pm »
Wait wait don't just send me on my way to some documentation. Ok so why isn't this code moving the piece left or right? It just moves it down at multiple times a second:
while(window.pollEvent(event)){
                if(event.type == (sf::Event::Closed))
                        window.close();
                //process movement detection of piece  
                if(event.type == (sf::Event::KeyPressed)){
                        switch(event.type){
                        case sf::Keyboard::Left:
                                level.GetGamePieces().at(temp - 1).GetPieceSprite().move(-10, 0);
                                std::cout << "left";
                                break;
                        case sf::Keyboard::Right:
                                level.GetGamePieces().at(temp - 1).GetPieceSprite().move(10,0);
                                std::cout << "right";
                                break;
                        }
                }
        }
        if(timeElapsed.asMilliseconds() >= 1000){
                level.GetGamePieces().at(temp - 1).GetPieceSprite().move(0,10);
                std::cout << "down";
                timeElapsed = clock.restart();
        }

Strelok

  • Full Member
  • ***
  • Posts: 139
    • View Profile
    • GitHub
Re: How to only get one input per key press during a loop?
« Reply #5 on: September 18, 2014, 02:55:06 pm »
Have you read the Official documentation (not some documentation) thoroughly?
if (event.key.code == sf::Keyboard::Left) // event.key.CODE
And also note:
Quote
If a key is held, multiple KeyPressed events will be generated, at the default OS delay (ie. the same delay that applies when you hold a letter in a text editor). To disable repeated KeyPressed events, you can call window.setKeyRepeatEnabled(false). On the contrary, obviously, KeyReleased events can never be repeated.

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: How to only get one input per key press during a loop?
« Reply #6 on: September 18, 2014, 08:44:48 pm »
Yeah, it's event.key.code for the actual key, not event.type.

Also, I'm not understanding your timing code. It looks like it's doing something wrongly.
It seems to be adding the accumulated clock's currently elapsed time (up to 100 seconds) each time, so at 99 seconds, it'll be adding 99 seconds onto the previously elapsed time, rather than the elapsed time being at 99 seconds.
Not sure what the 100 seconds thing is for but it looks like you should be doing something more like:
        if(timeElapsed.asSeconds() >= 100){
            timeElapsed = sf::Time::Zero;
        }
        // ...
        timeElapsed += clock.restart();
or
        if(timeElapsed.asSeconds() >= 100){
            timeElapsed = clock.restart();
        }
        // ...
        timeElapsed = clock.getElapsedTime();
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*