Статьи

Обработка событий клавиатуры и мыши в SDL2

Всем привет! В этой статье мы узнаем, как обрабатывать события клавиатуры и мыши, и будем использовать их для перемещения объекта по окну. Ура!

Начнем с изображения. Я сделал это растровое изображение 64 × 64:

космический корабль

Как видите, я не умею рисовать, чтобы спасти свою жизнь. Но так как это растровое изображение, нам не нужно расширение SDL_image.

Получив изображение, вы захотите создать новый проект Visual Studio, подключите его для работы с SDL2, а затем добавьте некоторый код для отображения окна и космического корабля в нем. Если вы не помните, как эти прошлые статьи должны помочь:

  1. « Настройка SDL2 с помощью Visual Studio 2015 »
  2. « Отображение пустого окна в SDL2 »
  3. « Отображение изображения в окне SDL2 »

Вы должны получить код, который выглядит примерно так:

#include <SDL.h>

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

    bool quit = false;
    SDL_Event event;
    int x = 288;
    int y = 208;

    // init SDL

    SDL_Init(SDL_INIT_VIDEO);
    SDL_Window * window = SDL_CreateWindow("SDL2 Keyboard/Mouse events",
        SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, 0);
    SDL_Renderer * renderer = SDL_CreateRenderer(window, -1, 0);

    SDL_Surface * image = SDL_LoadBMP("spaceship.bmp");
    SDL_Texture * texture = SDL_CreateTextureFromSurface(renderer,
        image);
    SDL_FreeSurface(image);

    SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);

    // handle events

    while (!quit)
    {
        SDL_WaitEvent(&event);

        switch (event.type)
        {
        case SDL_QUIT:
            quit = true;
            break;
        }

        SDL_Rect dstrect = { x, y, 64, 64 };

        SDL_RenderClear(renderer);
        SDL_RenderCopy(renderer, texture, NULL, &dstrect);
        SDL_RenderPresent(renderer);
    }

    // cleanup SDL

    SDL_DestroyTexture(texture);
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();

    return 0;
}

Вы также хотите , чтобы место spaceship.bmp  в вашу Debug папку (вместе с SDL2.dll ) , так что программа может найти файлы, необходимые ..

Как только вы действительно запустите программу, вы должны увидеть это:

sdl2-KBD-зарезки боковых стволов

Я установил белый фон окна, чтобы он соответствовал белому фону космического корабля, установив чистый цвет с помощью  SDL_SetRenderDrawColor () , а затем вызвав  SDL_RenderClear (),  чтобы очистить окно от этого цвета.

Для обработки событий клавиатуры и мыши нам нужен  SDL_Event . Хорошо, что вы знаете: мы использовали его все время, чтобы действовать, когда окно закрыто. Теперь нам нужно обработать другой тип события. Итак, давайте добавим новый case оператор после того, который обрабатывает SDL_QUIT:

            case SDL_KEYDOWN:

                break;

В этом case утверждении давайте теперь определим, какая клавиша была фактически нажата, и соответственно передвинем космический корабль:

            case SDL_KEYDOWN:
                switch (event.key.keysym.sym)
                {
                    case SDLK_LEFT:  x--; break;
                    case SDLK_RIGHT: x++; break;
                    case SDLK_UP:    y--; break;
                    case SDLK_DOWN:  y++; break;
                }
                break;

Если вы сейчас запустите программу, вы обнаружите, что можете перемещать космический корабль с помощью клавиш со стрелками:

sdl2-KBD-перемещение-медленно

Вы заметите, что он, кажется, движется довольно медленно, и вам нужно некоторое время нажимать, чтобы сделать какое-либо существенное движение. Теперь в своем коде замените  SDL_WaitEvent  на  SDL_PollEvent :

Теперь попробуйте запустить его снова:

sdl2-KBD перемещающихся-быстро

Swoosh! Менее чем за полсекунды космический корабль ударяется о край окна. Это на самом деле слишком быстро. Чтобы сделать это более понятным, добавьте небольшую задержку в начале while цикла:

        SDL_Delay(20);

SDL_PollEvent ()  лучше, чем  SDL_WaitEvent (),  когда вы хотите постоянно проверять (то есть опрашивать ) на наличие событий, но он потребляет больше ресурсов процессора (вы можете увидеть это, открыв диспетчер задач). SDL_WaitEvent ()  хорошо, когда ваше окно в основном бездействует, поэтому вам не нужно часто проверять события.

Обработка событий мыши также очень проста. Все, что вам нужно сделать, это обработать соответствующее событие. Давайте посмотрим, как справиться с щелчком мыши:

            case SDL_MOUSEBUTTONDOWN:
                switch (event.button.button)
                {
                    case SDL_BUTTON_LEFT:
                        SDL_ShowSimpleMessageBox(0, "Mouse", "Left button was pressed!", window);
                        break;
                    case SDL_BUTTON_RIGHT:
                        SDL_ShowSimpleMessageBox(0, "Mouse", "Right button was pressed!", window);
                        break;
                    default:
                        SDL_ShowSimpleMessageBox(0, "Mouse", "Some other button was pressed!", window);
                        break;
                }
                break;

И вот что происходит, когда вы запускаете его и щелкаете где-то в окне:

sdl2-KBD левой кнопкой мыши

Вы также можете отслеживать движение мыши и получить текущие координаты указателя мыши. Это полезно при перемещении объектов с помощью мыши (например, при перемещении объекта путем его перетаскивания). Следующий код получает координаты мыши и отображает их в заголовке окна:

            case SDL_MOUSEMOTION:
                int mouseX = event.motion.x;
                int mouseY = event.motion.y;

                std::stringstream ss;
                ss << "X: " << mouseX << " Y: " << mouseY;

                SDL_SetWindowTitle(window, ss.str().c_str());
                break;

Обратите внимание, что вам нужно добавить следующее в начало вашего main.cpp,  чтобы приведенный выше код работал:


#include <sstream>

Теперь вы заметите координаты мыши в заголовке окна:

sdl2-KBD-мышь-Coords

Замечательный! Теперь у вас должно быть представление о том, как захватывать и обрабатывать события клавиатуры и мыши в SDL2. Мы увидим больше об этом в следующей статье, посвященной рисованию пикселей в окне, так что следите за обновлениями, чтобы узнать больше!

Эта статья была первоначально опубликована как « SDL2: движение клавиатуры и мыши (события) » на ранчо программистов 12 февраля 2014 года. Она немного обновлена ​​здесь. Исходный код и космический корабль растровый доступны в репозитории Gigi Labs Bitbucket .