Входы в SDL (при нажатой клавише) - PullRequest
5 голосов
/ 18 сентября 2010

Я хотел бы знать, как я могу обнаружить нажатие клавиши или отпускание клавиши во время цикла в SDL.Теперь я знаю, что вы можете получать события с SDL, такие как OnKeyPressed, OnKeyReleased, OnKeyHit и т. Д., Но я хочу знать, как создавать функции, такие как KeyPressed, которые возвращают логическое значение, вместо того, чтобы быть событием.Пример:

while not KeyHit( KEY_ESC ) 
{
//Code here
}

Ответы [ 3 ]

11 голосов
/ 28 сентября 2010

Я знаю, что вы уже выбрали ответ ... но вот некоторый фактический код того, как я обычно делаю это с одним массивом. :)

сначала определите это где-нибудь.

bool KEYS[322];  // 322 is the number of SDLK_DOWN events

for(int i = 0; i < 322; i++) { // init them all to false
   KEYS[i] = false;
}

SDL_EnableKeyRepeat(0,0); // you can configure this how you want, but it makes it nice for when you want to register a key continuously being held down

Затем создайте функцию клавиатуры (), которая будет регистрировать ввод с клавиатуры

void keyboard() {
        // message processing loop
        SDL_Event event;
        while (SDL_PollEvent(&event)) {
            // check for messages
            switch (event.type) {
                // exit if the window is closed
            case SDL_QUIT:
                game_state = 0; // set game state to done,(do what you want here)
                break;
                // check for keypresses
            case SDL_KEYDOWN:
                KEYS[event.key.keysym.sym] = true;
                break;
            case SDL_KEYUP:
                KEYS[event.key.keysym.sym] = false;
                break;
            default:
                break;
            }
        } // end of message processing
}

Тогда, когда вы действительно хотите использовать ввод с клавиатуры, то есть функцию handleInput (), она может выглядеть примерно так:

void handleInput() {
    if(KEYS[SDLK_LEFT]) { // move left
        if(player->x - player->speed >= 0) {
            player->x -= player->speed;
        }
    }
    if(KEYS[SDLK_RIGHT]) { // move right
        if(player->x + player->speed <= screen->w) {
            player->x += player->speed;
        }
    }
    if(KEYS[SDLK_UP]) { // move up
        if(player->y - player->speed >= 0) {
            player->y -= player->speed;
        }
    }
    if(KEYS[SDLK_DOWN]) { // move down
        if(player->y + player->speed <= screen->h) {
            player->y += player->speed;
        }
    }
    if(KEYS[SDLK_s]) { // shoot 
        if(SDL_GetTicks() - player->lastShot > player->shotDelay) {
            shootbeam(player->beam);
        }
    }
    if(KEYS[SDLK_q]) {
        if(player->beam == PLAYER_BEAM_CHARGE) {
            player->beam = PLAYER_BEAM_NORMAL;
        } else {
            player->beam = PLAYER_BEAM_CHARGE;
        }
    }
    if(KEYS[SDLK_r]) {
        reset();
    }

    if(KEYS[SDLK_ESCAPE]) {
        gamestate = 0;
    }
}

И, конечно, вы можете легко сделать то, что вы хотите сделать

while(KEYS[SDLK_s]) {
    // do something
    keyboard(); // don't forget to redetect which keys are being pressed!
}

** Обновленная версия на моем сайте: ** Чтобы не публиковать много исходного кода, вы можете просмотреть полный класс SDL Keyboard в C ++, который поддерживает

  1. Одноклавишный ввод
  2. Одновременные комбинации клавиш (все клавиши нажаты в любом порядке)
  3. Последовательные сочетания клавиш (все клавиши нажаты в определенном порядке)

http://kennycason.com/posts/2009-09-20-sdl-simple-space-shooter-game-demo-part-i.html (если у вас есть какие-либо проблемы, дайте мне знать)

0 голосов
/ 05 января 2014

У меня была эта проблема в LuaJIT с FFI, вот как я ее решил:

Global:

KEYS = {}

Код события:

ev = ffi.new("SDL_Event[1]")
function event()
    while sdl.SDL_PollEvent(ev) ~= 0 do
        local e = ev[0]
        local etype = e.type
        if etype == sdl.SDL_QUIT then
            return false -- quit
            -- os.exit() -- prevents interactive mode
        elseif etype == sdl.SDL_KEYDOWN then
            if e.key.keysym.sym == sdl.SDLK_ESCAPE then
                return false -- quit
                -- os.exit()
            end
            print("Pressed: ", e.key.keysym.scancode, "\n")
            KEYS[tonumber(e.key.keysym.sym)] = true
            -- print("Pressed: ", (e.key.keysym.sym == sdl.SDLK_w), "\n");
        elseif etype == sdl.SDL_KEYUP then
            KEYS[tonumber(e.key.keysym.sym)] = false
        elseif etype == sdl.SDL_VIDEORESIZE then
            -- print("video resize W:".. e.resize.w .. " H:" .. e.resize.h)
            width = e.resize.w
            height = e.resize.h
            onResize()
        end
    end
    return true -- everything ok
end

Функция обновления:

if KEYS[sdl.SDLK_w] == true then
    rot = rot + 1
end

Большую часть времени я потратил на это:

KEYS[tonumber(e.key.keysym.sym)] = false

Поскольку FFI возвращает объект CData, который использовался в качестве ключа массива, но для него требуется целое число.

0 голосов
/ 18 сентября 2010

У вас должно быть 2 таблицы логических значений для ключей.Одна таблица, в которой вы устанавливаете ключи true или false на основе событий keydown / keyup SDL, а другая - инициализацию с помощью false.При проверке keyPressed вы просто сравниваете второй ключ таблицы с первым ключом таблицы, и, если он отличается, если второй ключ таблицы ложен, он был нажат, иначе он был отпущен.После этого вы делаете secondTable [ключ]: = не secondTable [ключ].Работает!

...