SDL / C EventHandler连续密钥

时间:2016-12-30 19:54:52

标签: c events sdl

我正在尝试使用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];
        }
    }
}

1 个答案:

答案 0 :(得分:0)

问题在于,SDL 2.0.4存在一个错误,即在按键之间按住键发送键,而不是连续按键。下载最新版本修复了问题。