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

Author Topic: KeyPressed triggers once and then continuously after being held for a while  (Read 5006 times)

0 Members and 1 Guest are viewing this topic.

BenjaminBlodgett

  • Newbie
  • *
  • Posts: 2
    • View Profile
Title basically says what the issue is. I imagine this is intentional, but is there a way to turn it off or do I just have to work around it? Maybe it's platform specific?

Additionally, I'd appreciate if anyone could share some elegant solutions to event handling. The way I'm doing it now requires me to update 4 different switch statement cases every time I want to add a new input.

#pragma once

#include <SFML/Graphics.hpp>
#include "button.h"

#include <iostream>

struct Input : public sf::Event {
public:
    enum button_key_codes {
        ESCAPE = sf::Keyboard::Escape,
    };

    button escape{ "Escape" };

    void update() {

        switch (type) {

        case sf::Event::Closed:
            //std::cout << "closed" << std::endl;
            break;
           
        case sf::Event::KeyPressed:
           
            switch (key.code) {

            case (ESCAPE):
                escape.press();
                break;

            }
           
            break;
           
        case sf::Event::KeyReleased:
           
            switch (key.code) {

            case (ESCAPE):
                escape.release();
                break;

            }
           
            break;

        default:
            escape.clear_press_and_release();
            break;

        }
    }

    void assume_no_input() {
        escape.clear_press_and_release();
    }
};

I've thought about using std::vector and if statements, but I'm afraid of venturing away from switch statements because I assume they are the standard and most performant method for input handling in SFML.

kojack

  • Sr. Member
  • ****
  • Posts: 343
  • C++/C# game dev teacher.
    • View Profile
In your setup code, tell the main window to turn off key repeat.
window.setKeyRepeatEnabled(false);

Windows has a keyboard repeat delay and repeat rate, you can set them in the keyboard preferences. When a key is pressed, windows sends WM_KEYDOWN. If it is still down after the repeat delay, windows starts sending WM_KEYDOWN with the KF_REPEAT flag at the rate in the preferences. When finally released, WM_KEYUP is sent.
So by default SFML uses the way windows is sending it (held key makes lots of down events, only 1 up event), unless you turn that off with setKeyRepeatEnabled.

(I don't know if other operating systems do it that way too, I'm just a windows coder)
« Last Edit: January 22, 2022, 10:40:59 am by kojack »

Stauricus

  • Sr. Member
  • ****
  • Posts: 369
    • View Profile
    • A Mafia Graphic Novel
    • Email
you can also use the KeyReleased event instead. most games do that (except for text entering or other continuous actions, like moving the screen with the arrows)
Visit my game site (and hopefully help funding it? )
Website | IndieDB

BenjaminBlodgett

  • Newbie
  • *
  • Posts: 2
    • View Profile
In your setup code, tell the main window to turn off key repeat.
window.setKeyRepeatEnabled(false);

Windows has a keyboard repeat delay and repeat rate, you can set them in the keyboard preferences. When a key is pressed, windows sends WM_KEYDOWN. If it is still down after the repeat delay, windows starts sending WM_KEYDOWN with the KF_REPEAT flag at the rate in the preferences. When finally released, WM_KEYUP is sent.
So by default SFML uses the way windows is sending it (held key makes lots of down events, only 1 up event), unless you turn that off with setKeyRepeatEnabled.

(I don't know if other operating systems do it that way too, I'm just a windows coder)

Brilliant, thank you!