2016-12-30 7 views
0

私はSDLを使ってCでイベントハンドラを開発しようとしています。SDL/C EventHandler continuous key

私は以下のことを検出できるようにしたいと考えました:キーが押され、キーが離され、キーが押されています。

問題は、キーボードの自動リピートが一定の遅延と所定の間隔でキーを押したことです。これを軽減するために、私は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