2016-12-30 3 views
0

Я пытаюсь разработать обработчик событий в C, используя SDL.SDL/C EventHandler непрерывный ключ

Я хотел бы обнаружить следующие вещи: нажатие клавиши, нажатие клавиши и нажатие клавиши.

Проблема в том, что клавиатура автоматически повторяет спам нажатием клавиш после определенной задержки и с заданным интервалом. Чтобы смягчить это, я попытался использовать 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]; 
     } 
    } 
} 
+0

Вы проверили возвращаемое значение 'SDL_EnableKeyRepeat'? Он должен возвращать '0' на успех. – emlai

+0

это удачный, но ничего другого не наблюдается. –

+0

В большинстве случаев вы не можете отключить повтор ключа, но в ключевом случае есть поле 'repeat', чтобы вы могли отфильтровать эти события. 'SDL_GetKeyboardState' - это просто отражение прошлых событий. – keltar

ответ

0

Проблема заключалась в том, что SDL 2.0.4 была ошибка, где удерживая ключ послал ключевых релизов в период между нажатиями клавиш вместо непрерывных нажатий клавиш. Исправлена ​​проблема с загрузкой последней версии.

+1

Пожалуйста, выберите свой ответ, чтобы принять его (добавьте зеленую галочку слева). Это даст понять другим, что эта проблема решена. – user694733

Смежные вопросы