SDL2 和测量按键时间
SDL2 and measuring the time a key is pressed
我已经编写了以下(典型)代码片段来处理 SDL2 中的关键事件:
#include <SDL.h>
#include <iostream>
using std::cout;
using std::endl;
// Custom key types
typedef enum Keys {
Back,
Reset
} KeyType;
// Structure that holds the type and pressed state of custom keys
typedef struct Button {
KeyType type;
bool pressed;
} Button;
int main(int argc, char ** argv)
{
// Variables
bool quit = false;
SDL_Event event;
Button buttons[] = {
{Back, false},
{Reset, false}
};
// Initialize SDL sub-systems, window, renderer and texture
SDL_Init(SDL_INIT_VIDEO);
SDL_Window * window = SDL_CreateWindow("SDL2 Keyboard/Mouse events",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 640, 0);
SDL_Renderer * renderer = SDL_CreateRenderer(window, -1, 0);
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
// Loop while quit not disabled
while (!quit)
{
// Pool events
while(SDL_PollEvent(&event))
{
// Filter events
switch (event.type)
{
case SDL_QUIT: // Window closed
quit = true;
break;
case SDL_KEYDOWN: // Key pressed
switch (event.key.keysym.sym)
{
case SDLK_ESCAPE:
quit = true;
break;
case SDLK_LEFT:
buttons[Back].pressed = true; // Toggle Back button to pressed
cout << "Back held" << endl;
// TODO Measure elapsed time and artificially toggle the pressed state to false if > 5s
break;
case SDLK_DOWN:
buttons[Reset].pressed = true; // Toggle Reset button to pressed
break;
}
break;
case SDL_KEYUP: // Key released
switch (event.key.keysym.sym)
{
case SDLK_LEFT:
if (buttons[Back].pressed) {
// TODO Measure elapsed time and print "Back emitted" if less than 5s
buttons[Back].pressed = false; // Toggle Back button to unpressed and emit Back event
}
break;
case SDLK_DOWN:
buttons[Reset].pressed = false; // Toggle Reset button to unpressed
cout << "Reset emitted" << endl;
break;
}
break;
case SDL_USEREVENT:
break;
}
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
}
}
// Cleanup resources
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
// Stop all SDL sub-systems
SDL_Quit();
return 0;
}
我正在尝试找出一种方法来测量 buttons[Back].pressed
设置为 true
的时刻之间的时间(即使仅在 "holding" 是我感兴趣的)然后到 false
。 "key released" 部分很简单,因为这只是一个事件。
我想区分 short(收到单个 "key pressed" 事件或持有密钥少于 5s)和 long(按住键超过 5 秒)strokes 这基本上是根据用户按住键的时间将两个动作映射到同一个键。
我不知道该怎么做。有任何想法吗?我需要在两个位置处理时间事件(恕我直言):
- 给定的键被释放 - 如果经过的时间是 less/equal 到 5s 检测到 短击键 否则 长击键
- 当给定键被按下时 - 如果超时开始,按下状态需要人为切换到
false
以防止 短击键 当用户实际释放键时被检测到。在这种情况下,检测到长击键
我扩展了@keltar 的建议,虽然不是那么精确,但它确实有效(但在我的情况下,它不是必需的。
我在 Button
结构中添加了 elapsedTime
来保存时间信息并将其初始化为 0
:
typedef struct Button {
KeyType type;
bool pressed;
uint32_t elapsedTime;
} Button;
每当按下给定的键时,我检查是否 elapsedTime == 0
,如果是,我调用 SDL_GetTicks()
。释放密钥后,我得到了 currentTime
,这只是当时 SDL_GetTicks()
的另一个调用。我计算 elapsedTime
和 currenTime
之间的差异,并检查特定时间间隔是否已经过去,然后决定调用哪个函数。
可以通过在每次循环迭代期间进行上述计算并进行完全相同的检查来扩展此解决方案。这使得不仅可以在释放给定密钥时检查经过的时间,而且它是对我最初问题的更准确的答案。然而,第一个解决方案(没有额外检查)工作正常。我只需要稍微调整一下我的场景。
我已经编写了以下(典型)代码片段来处理 SDL2 中的关键事件:
#include <SDL.h>
#include <iostream>
using std::cout;
using std::endl;
// Custom key types
typedef enum Keys {
Back,
Reset
} KeyType;
// Structure that holds the type and pressed state of custom keys
typedef struct Button {
KeyType type;
bool pressed;
} Button;
int main(int argc, char ** argv)
{
// Variables
bool quit = false;
SDL_Event event;
Button buttons[] = {
{Back, false},
{Reset, false}
};
// Initialize SDL sub-systems, window, renderer and texture
SDL_Init(SDL_INIT_VIDEO);
SDL_Window * window = SDL_CreateWindow("SDL2 Keyboard/Mouse events",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 640, 0);
SDL_Renderer * renderer = SDL_CreateRenderer(window, -1, 0);
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
// Loop while quit not disabled
while (!quit)
{
// Pool events
while(SDL_PollEvent(&event))
{
// Filter events
switch (event.type)
{
case SDL_QUIT: // Window closed
quit = true;
break;
case SDL_KEYDOWN: // Key pressed
switch (event.key.keysym.sym)
{
case SDLK_ESCAPE:
quit = true;
break;
case SDLK_LEFT:
buttons[Back].pressed = true; // Toggle Back button to pressed
cout << "Back held" << endl;
// TODO Measure elapsed time and artificially toggle the pressed state to false if > 5s
break;
case SDLK_DOWN:
buttons[Reset].pressed = true; // Toggle Reset button to pressed
break;
}
break;
case SDL_KEYUP: // Key released
switch (event.key.keysym.sym)
{
case SDLK_LEFT:
if (buttons[Back].pressed) {
// TODO Measure elapsed time and print "Back emitted" if less than 5s
buttons[Back].pressed = false; // Toggle Back button to unpressed and emit Back event
}
break;
case SDLK_DOWN:
buttons[Reset].pressed = false; // Toggle Reset button to unpressed
cout << "Reset emitted" << endl;
break;
}
break;
case SDL_USEREVENT:
break;
}
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
}
}
// Cleanup resources
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
// Stop all SDL sub-systems
SDL_Quit();
return 0;
}
我正在尝试找出一种方法来测量 buttons[Back].pressed
设置为 true
的时刻之间的时间(即使仅在 "holding" 是我感兴趣的)然后到 false
。 "key released" 部分很简单,因为这只是一个事件。
我想区分 short(收到单个 "key pressed" 事件或持有密钥少于 5s)和 long(按住键超过 5 秒)strokes 这基本上是根据用户按住键的时间将两个动作映射到同一个键。
我不知道该怎么做。有任何想法吗?我需要在两个位置处理时间事件(恕我直言):
- 给定的键被释放 - 如果经过的时间是 less/equal 到 5s 检测到 短击键 否则 长击键
- 当给定键被按下时 - 如果超时开始,按下状态需要人为切换到
false
以防止 短击键 当用户实际释放键时被检测到。在这种情况下,检测到长击键
我扩展了@keltar 的建议,虽然不是那么精确,但它确实有效(但在我的情况下,它不是必需的。
我在 Button
结构中添加了 elapsedTime
来保存时间信息并将其初始化为 0
:
typedef struct Button {
KeyType type;
bool pressed;
uint32_t elapsedTime;
} Button;
每当按下给定的键时,我检查是否 elapsedTime == 0
,如果是,我调用 SDL_GetTicks()
。释放密钥后,我得到了 currentTime
,这只是当时 SDL_GetTicks()
的另一个调用。我计算 elapsedTime
和 currenTime
之间的差异,并检查特定时间间隔是否已经过去,然后决定调用哪个函数。
可以通过在每次循环迭代期间进行上述计算并进行完全相同的检查来扩展此解决方案。这使得不仅可以在释放给定密钥时检查经过的时间,而且它是对我最初问题的更准确的答案。然而,第一个解决方案(没有额外检查)工作正常。我只需要稍微调整一下我的场景。