SDL2并测量按下按键的时间

时间:2017-04-28 15:15:03

标签: c++ time key sdl-2

我已经编写了以下(典型)代码片段来处理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之间的时间(即使只按住键的确切开头时#) 34;持有&#34;是我感兴趣的)然后到false。 &#34;密钥已发布&#34;部分很容易因为这是一个单一的事件。

我想要区分(单击&#34;按键&#34;收到的事件或持有的键少于让#5说)和(按住键超过5秒)笔画,基本上是根据用户持有密钥的时间将两个操作映射到同一个键。

我无法弄清楚如何做到这一点。有任何想法吗?我需要在两个位置(imho)处理时间事件:

  • 给定密钥已释放 - 如果已用时间小于/等于5秒,则检测到短按键否则长按键
  • 在按下给定键的同时 - 如果超时启动,则需要将按下的状态人为切换为false,以防止在检测到短按键时用户实际释放密钥。在这种情况下,检测到长键击

1 个答案:

答案 0 :(得分:0)

我对@keltar的建议进行了扩展,虽然不是那么精确(但在我看来并不是必需的。)

我在elapsedTime结构中添加Button来保存时间信息并将其初始化为0

typedef struct Button {
    KeyType type;
    bool pressed;
    uint32_t elapsedTime;
} Button;

每当按下给定的键时,我会检查elapsedTime == 0是否如此,如果是,请拨打SDL_GetTicks()。在释放密钥后,我得到currentTime,这是该时间点SDL_GetTicks()的另一个呼叫。我计算elapsedTimecurrenTime之间的差异,并检查是否已经过了特定的时间间隔,然后决定调用哪个函数。

通过在每次循环迭代期间进行上述计算并进行完全相同的检查,可以扩展此解决方案。这使得可以不仅在释放给定键时检查经过的时间,而且这是对我的初始问题的更准确的答案。然而,第一个解决方案(没有额外检查)工作正常。我只需稍微调整一下我的情景。