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

Author Topic: Help using in-window key input inside KeyPressed event with switch  (Read 1115 times)

0 Members and 1 Guest are viewing this topic.

jhain

  • Newbie
  • *
  • Posts: 1
    • View Profile
Hi, I'm working on a basic game and can't figure out how to get player input to register.

I'm using sf::Event::KeyPressed with switch(event.key.code) to control WASD movement (top down grid-based turn-based dungeon crawler style) within the main window.pollEvent(event) and got it to work without errors.

I want to press another key to throw an item, but I can't figure out how to trigger another WASD switch for direction of the throw. Here's the broken code I have so far:


(click to show/hide)

I got it to work using cin, but how would I get it to work in the window itself? I understand it's just skipping over the inner if statement. I believe I need to involve another Event but I'm scratching my head. Should I be relocating all of the movement/input keys outside of the while (window.pollEvent(event)) statement? I've read the Event / Input / Keyboard tutorial pages multiple times but still need some help!

First post! Haven't been using SFML very long and rusty with C++ so bear with me :)

Garwin

  • Jr. Member
  • **
  • Posts: 59
    • View Profile
Re: Help using in-window key input inside KeyPressed event with switch
« Reply #1 on: April 20, 2023, 08:06:11 pm »
Do you have a loop? Your code seems inefficient but not completely wrong as if your C key is pressed at the time of condition it looks on the event and check it. So it going for each event.

I would suggest using function isKeyPressed() for both. The only disadvantage it can have is that your press it for shorter time than 1 fps. But I do not think that this is something you can worry about.

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: Help using in-window key input inside KeyPressed event with switch
« Reply #2 on: April 20, 2023, 11:17:19 pm »
Mixing real-time keyboard input (isKeypressed) into the event loop gets really messy quickly and can be relatively easily avoided.

First, you could check the real-time stuff together (outside of the event loop) and then set boolean 'flags' to control how to respond when an event is triggered. Very similar to your idea but without actually checking the key on every event.

Second, it could be better to do the event check first and, upon it being the correct event, then check to see if the other key is pressed (using either direct method or the method I mentioned above, for examples).

I envision this something like this:
while (window.isOpen())
{
    sf::Event event;
    while (window.pollEvent(event))
    {
        switch (event.type)
        {
        case sf::Event::Keypressed:
            switch (event.key.code)
            {
                case sf::Keyboard::W:
                    // is C pressed? do something for that. if not, do something else if you want to
                break;
            }
        break;
        }
    }
}

However, looking at what your code seems to want do, it looks like you want to trigger throw when you press the key and then throw on the next key if still pressed.
Note that in your version, you are outputing text every frame that C is pressed.

So, you can use events for both (this is the code I'm suggesting you consider):
bool isReadyToThrow{ false };
while (window.isOpen())
{
    sf::Event event;
    while (window.pollEvent(event))
    {
        switch (event.type)
        {
        case sf::Event::Keypressed:
            switch (event.key.code)
            {
                case sf::Keyboard::C:
                    if (hasItem)
                    {
                        if (!isReadyToThrow)
                            std::cout << "Which direction?\n";
                        isReadyToThrow = true;
                    }
                break;
                case sf::Keyboard::W:
                    if (isReadyToThrow)
                    {
                        throwUp();
                        hasItem = false;
                        isReadyToThrow = false;
                    }
                break;
                case sf::Keyboard::S:
                    if (isReadyToThrow)
                    {
                        throwDown();
                        hasItem = false;
                        isReadyToThrow = false;
                    }
                break;
                case sf::Keyboard::A:
                    if (isReadyToThrow)
                    {
                        throwLeft();
                        hasItem = false;
                        isReadyToThrow = false;
                    }
                break;
                case sf::Keyboard::D:
                    if (isReadyToThrow)
                    {
                        throwRight();
                        hasItem = false;
                        isReadyToThrow = false;
                    }
                break;
            }
        break;
        case sf::Event::Keyreleased:
            switch (event.key.code)
            {
                case sf::Keyboard::C:
                    isReadyToThrow = false;
                break;
            }
        break;
        }
    }
}

Remember that events should be checked constantly so "throwUpwards()" should either be instantaneous or should trigger an action that would continue elsewhere (probably in an update section of the loop). It's usually best to avoid code that takes a long time to be triggered from with the event loop, stopping it from completing the event loop.


Is it just me that noticed that throwUp and throwDown have different meanings as well? :D
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*