私は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];
}
}
}
'SDL_EnableKeyRepeat'の戻り値を確認しましたか?成功すると '0'を返します。 – emlai
それは成功していますが、何も違うことは認められません。 –
ほとんどの場合、キーリピートを無効にすることはできませんが、キーイベントには 'repeat'フィールドがありますので、これらのイベントをフィルタリングすることができます。 'SDL_GetKeyboardState'は過去のイベントを反映したものに過ぎません。 – keltar