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 这基本上是根据用户按住键的时间将两个动作映射到同一个键。

我不知道该怎么做。有任何想法吗?我需要在两个位置处理时间事件(恕我直言):

我扩展了@keltar 的建议,虽然不是那么精确,但它确实有效(但在我的情况下,它不是必需的。

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

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

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

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