SDL/C EventHandler连续键

SDL/C EventHandler continuous key

我正在尝试使用 SDL 在 C 中开发事件处理程序。

我希望能够检测到以下内容:按键按下、按键释放和按键按下。

问题是键盘会在一定的延迟后以给定的时间间隔自动重复垃圾按键。为了缓解这种情况,我尝试使用 SDL_EnableKeyRepeat(0, 0);根据文档,哪个应该禁用它?

由于失败,我尝试映射 SDL_GetKeyboardState(NULL);它有点管用。但我遇到的问题是,如果我按住一个键 X 秒,它会在相同的时间内发送垃圾邮件幽灵事件。

按下 esc,按住它一会儿,然后松开它的示例输出是:

Pressed
HELD
HELD
HELD
... 
RELEASED       {it breaks down after first proper release}
PRESSED        
RELEASED 
HELD
PRESSED 
RELEASED 
HELD
...
RELEASED     // it always ends on released.

上面的结果是:

Pressed: 18;
Released: 21;
Held: 39.

Should be:
Pressed 1;
Released 1;
Held: say 20. 

不确定我的逻辑是否以某种方式搞砸了,或者它是否与键盘事件的实际内置机制有关。

代码如下:

/** 程序界面

    void ev_handle_start()      // Starts the Event Handler.
    void ev_handle_stop()       // Pauses the Event Handler.

**/

#include <stdio.h>
#include <SDL2/SDL.h>
#include <SDL/SDL.h>
#include "ev_handler.h"

#define PRESSED             1
#define RELEASED            0
#define TMR_FREQ            33
#define MOUSE_RIGHT         1
#define MOUSE_LEFT          3
#define EV_LEFT_CLICK       0
#define EV_LEFT_RELEASE     1
#define EV_RIGHT_CLICK      2
#define EV_RIGHT_RELEASE    3
#define EV_MOUSE_MAX        4
#define MAX_SCANCODES       SDL_SCANCODE_MODE
#define EV_DELAY            70

//********************************************************************************************//
//      VARIABLES
//********************************************************************************************//

SDL_Event e;
Uint8* keyboardState;
SDL_TimerID ev_timer = NULL;                // Timer to callback the search of the code
bool ev_handler_active = false;             // Used to determine if the ev_handler() is enabled or not
bool buttonState[EV_MOUSE_MAX];             // Button Stats, either pressed or released
bool evMouseEvent[EV_MOUSE_MAX];            // Used to flag if a mouse events
int evKeyEventStatus[MAX_SCANCODES];
bool evKeyStatePrev[MAX_SCANCODES];         //
bool evKeyStateCur[MAX_SCANCODES];          //

//********************************************************************************************//
//  1   FRONTEND
//********************************************************************************************//

//********************************************************************************************//
//  1.1 MOUSE
//      Can only handle left and right mouse buttons.
//********************************************************************************************//
bool evButtonPressed(int button)
{   bool flag = button == SDL_BUTTON_RIGHT || button == SDL_BUTTON_LEFT;
    if (!flag) {
        printf("ERROR: isButtonPressed(int) received parameter of invalid type.\n");
        return false;
    }
    return buttonState[button];
}

bool evLeftClick()
{
    return evMouseEvent[EV_LEFT_CLICK];
}

bool evLeftRelease()
{
    return evMouseEvent[EV_LEFT_RELEASE];
}

bool evRightClick()
{
    return evMouseEvent[EV_RIGHT_CLICK];
}

bool evRightRelease()
{
    return evMouseEvent[EV_RIGHT_RELEASE];
}

//********************************************************************************************//
//  1.2 KEYBOARD
//********************************************************************************************//
bool evKeyHeld(SDL_Scancode sc)
{
    return evKeyEventStatus[sc] == 1 || evKeyEventStatus[sc] == 3;
}

bool evKeyPressed(SDL_Scancode sc)
{
    return evKeyEventStatus[sc] == 1;
}

bool evKeyReleased(SDL_Scancode sc)
{
    return evKeyEventStatus[sc] == 2;
}

//********************************************************************************************//
//  1.3 MANAGE
//********************************************************************************************//
void evSetup()
{
    for (int i = 0; i < MAX_SCANCODES; i++) {
        evKeyStatePrev[i] = 0;
    }
    evClearEvents();
}

int j;
void evClearEvents()
{
    evMouseEvent[EV_LEFT_CLICK] = false;
    evMouseEvent[EV_LEFT_RELEASE] = false;
    evMouseEvent[EV_RIGHT_CLICK] = false;
    evMouseEvent[EV_RIGHT_RELEASE] = false;
}

//********************************************************************************************//
//  2   BACKEND
//********************************************************************************************//
void ev_handler()
{
    while(SDL_PollEvent(&e))
    {
        switch (e.type)
        {
            /*Skip unnecessary events*/
            case SDL_KEYDOWN:
                break;
            case SDL_KEYUP:
                break;
            case SDL_MOUSEMOTION:
                break;

            case SDL_MOUSEBUTTONDOWN:
                buttonState[e.button.button] = PRESSED;
                if (e.button.button == SDL_BUTTON_LEFT) {
                    evMouseEvent[EV_LEFT_CLICK] = true;
                }
                else if (e.button.button == SDL_BUTTON_RIGHT) {
                    evMouseEvent[EV_RIGHT_CLICK] = true;
                }
                break;

            case SDL_MOUSEBUTTONUP:
                buttonState[e.button.button] = RELEASED;
                if (e.button.button == SDL_BUTTON_LEFT) {
                    evMouseEvent[EV_LEFT_RELEASE] = true;
                }
                else if (e.button.button == SDL_BUTTON_RIGHT) {
                    evMouseEvent[EV_RIGHT_RELEASE] = true;
                }
                break;

            case SDL_QUIT:
                exit(0);
                printf("Quit\n");
                break;

            default:
                break;
        }

        keyboardState = SDL_GetKeyboardState(NULL);

        for (int i = 0;  i < MAX_SCANCODES; i++)
        {
            evKeyStateCur[i]  = keyboardState[i];
            int sum = evKeyStateCur[i] + evKeyStatePrev[i]*2;
            switch (sum) {
                case  0:
                    break;

                case 1:
                    evKeyEventStatus[i] = 1;
                    break;

                case 2:
                    evKeyEventStatus[i] = 2;
                    break;

                case 3:
                    evKeyEventStatus[i] = 3;
                    break;

                default: evKeyEventStatus[i] = 0; break;
            }
            evKeyStatePrev[i] = evKeyStateCur[i];
        }
    }
}

问题是 SDL 2.0.4 有一个错误,即按住一个键会在两次按键之间发送按键释放,而不是连续按键。下载最新版本解决了这个问题。