如何在 SDL 2.0 中实时获取所有事件的 "list"?

How do I get a "list" of ALL the events in real time in SDL 2.0?

我来自 Pygame, and there I had pygame.event.get(),它返回了所有事件的列表(因此,一旦我在主循环中有了该事件列表,我就可以实时检查多个按键或其他任何内容,因为所有可能的事件可用)。

现在这是我的代码:

#include "init.h"
#include "texture.h"

int main(int argc, char** argv) {

    Init();

    while (running) {
        while (SDL_PollEvent(&e) != 0) { // PROBLEM <<< I don't want "POLL".
            auto key = e.key.keysym.sym;
            if (e.type == SDL_QUIT) {
                running = false;
            } else if (e.type == SDL_KEYDOWN) {
                if (key == SDLK_ESCAPE) {
                    running = false;
                }
                if (key == SDLK_UP) {
                    square_rect.y -= PLAYER_SPEED;
                } else if (key == SDLK_DOWN) {
                    square_rect.y += PLAYER_SPEED;
                } else if (key == SDLK_LEFT) {
                    square_rect.x -= PLAYER_SPEED;
                } else if (key == SDLK_RIGHT) {
                    square_rect.x += PLAYER_SPEED;
                }
            }

        }

        SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
        SDL_RenderClear(renderer);
        SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
        SDL_RenderFillRect(renderer, &square_rect);
        SDL_RenderPresent(renderer);

    }

    SDL_DestroyWindow(window);
    SDL_Quit();
    return 0;
}

到目前为止,在我看到的教程中,他们使用了 SDL_PollEvent(),直到现在,当我尝试使用键盘箭头移动我的方块时,我才注意到其中的区别。显然,我不能同时按下两个箭头键,因为循环一次捕获一个事件。

问题是,API 中没有 "SDL_Event_Get()" 这样的东西。只有这些:

嗯,我不知道 Pete Shinners 如何将 SDL 1.2 移植到 Python 并以如此奇妙的方式处理事件,所以我很难理解 SDL 2.0(我可能不是唯一的)。 SDL 2.0中有"get all the events ()"这样的东西吗?如果我想检查是否所有可能的键都在同一时间被按下怎么办?

您可以按照 the documentation:

中的说明使用 SDL_GetKeyboardState
const Uint8 *state = SDL_GetKeyboardState(NULL);
if (state[SDL_SCANCODE_RETURN]) {
    printf("<RETURN> is pressed.\n");
}
if (state[SDL_SCANCODE_RIGHT] && state[SDL_SCANCODE_UP]) {
    printf("Right and Up Keys Pressed.\n");
}

一般来说,您可以将事件提取到任何容器中,然后检查该容器中是否有任何数量的事件。一个好的容器是 std::setstd::unordered_set,但在这两种情况下,您都必须为类型 SDL_Event 定义 operator<std::hash

另一种方法是制作您自己的适用于任何容器的通用算法:

template<typename OutIt>
void push_events(OutIt out) {
    SDL_Event e;
    while (SDL_PollEvent(&e) != 0)
        *out++ = e;
}

然后将其应用于选择的某个容器,例如 std::vector:

std::vector<SDL_Event> vector;
push_events(std::back_inserter(vector));

另一种选择是保持您自己的 std::set 键被按下,其中 "remember" 在任何给定时刻按下了哪些键。

例如,给定:

std::set<SDL_Keycode> keys;

然后:

SDL_Event e;
while (SDL_PollEvent(&e) != 0) {
    switch (e.type) {
    case SDL_KEYDOWN:
        auto key = e.key.keysym.sym;
        keys.insert(key);
        break;
    case SDL_KEYUP:
        auto key = e.key.keysym.sym;
        keys.erase(key);
        break;
    }
}

然后通过以下方式检查:

if (keys.count(SDLK_SPACE) && keys.count(SDLK_UP))
    // ...

但我不确定你买的是什么。