Как в графическом режиме вводить данные с клавиатуры sdl

Обновлено: 07.07.2024

Я запускаю метод update() n раз в секунду для "обновления" ввода клавиатуры от пользователя, поэтому я могу прочитать его позже в логической части программы. Поэтому я нашел два способа реализации этого в SDL Docs, и я не уверен, какой из них мне следует использовать.

1; Loop для всех событий, использующих SDL_PollEvent, для поиска событий нажатия клавиш/сохранения и сохранения состояний клавиш на карте, поэтому я могу проверить каждое состояние ключа в логике программы.

Примечание. В качестве альтернативы я также могу использовать SDL_PeepEvents вместо SDL_PollEvent, чтобы принимать только те типы событий, которые имеют значение; поэтому он не "выбросил" события в очередь.

2; Принимая снимок с клавиатуры каждый кадр, чтобы я мог легко прочитать его.

С любой из вышеперечисленных реализаций я могу читать keyboard так:

Кроме того, есть ли другой способ сделать это?

Я предпочитаю делать вариацию 1, где я заполняю три массива, указывая не только на текущее состояние, но и на то, какие ключи просто спустились и какие клавиши просто поднялись. Это позволяет мне легко проверять эти события в коде (без сравнения с предыдущим снимком), но, самое главное, он не пропустит события, которые меньше, чем кадр. Например, если ваша игра работает на скорости 10 кадров в секунду из-за медленной машины, пользователь может нажать и отпустить важный ключ между двумя вызовами вашей процедуры обновления, а затем ваша система никогда не зарегистрирует его. Это очень расстраивает.

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

Вы должны использовать решение 2.

Почему? Как SDL_GetKeyState() указатели указывают, прежде чем использовать его, вы должны называть SDL_PumpEvents() , чтобы обновить массив состояний.

Когда вы вызываете SDL_PollEvent() , он неявно вызывает SDL_PumpEvents() . Таким образом, он в любом случае обновляет массив для SDL_GetKeyState() . Разбирая эти события вручную, вы просто создаете второй массив (ну, на самом деле, гораздо более медленную карту), содержащую ту же информацию, которую SDL уже собрал для вас.

Итак, я бы посмел сказать, что первое решение означает делать то же самое дважды. И если вы когда-нибудь решите поддержать такие вещи, как повторные нажатия клавиш (SDL_EnableKeyRepeat()), вы будете переопределять даже большую часть SDL.

Я понимаю, что этот вопрос довольно старый, но мой ответ может кому-то помочь. Лично я использую два массива с SDL_GetKeyState . Я храню один массив, содержащий текущее состояние клавиатуры кадра, и один массив, содержащий состояние последней кадровой клавиатуры. (С некоторыми командами memcpy их очень легко обновить.) Наряду с этими двумя массивами у меня есть карта, которая преобразует строки, такие как "A", в значения scancode SDL, но это необязательно.

Затем, когда вам нужно проверить, что что-то выпущено или нажато, вы можете объединить два массива для проверки. (Я сделал это функцией.) Например, если вы знаете, что клавиша нажата на этот кадр, но не был нажат последний кадр, это было просто нажато на этот кадр. if (currentFrame["A"] == true && lastFrame["A"] == false)

Тогда вы сделали бы противоположное для освобожденных. Я считаю, что этот метод очень просто реализовать и использовать.

Посмотрите другие вопросы по меткам input keyboard sdl или Задайте вопрос

lesson4_1
lesson4_2

alphabet

И так, какие у нас есть варианты для отображения текста. На базе нашей библиотеки для управления спрайтами (а лучше второй версии) можно написать свою простую библиотеку для работы с текстом. Вместо кадров анимации мы будем загружать из изображения буквы. Примером такого изображения может служить вот это:

Как я уже упоминал в предыдущих уроках, штатными средствами SDL мы можем загружать только файлы BMP. Но при помощи SDL_image мы можем работать с практически любым форматом изображения. Файл нашего растрового шрифта имеет формат PNG (Portable Network Graphics). Чтобы загрузить такой файл мы используем функцию IMG_Load из библиотеки SDL_image . Вот ее прототип: SDL_Surface* IMG_Load(const char* file);
И все! Таким нехитрым способом можно загрузить на поверхность SDL_Surface любую графику. И давайте посмотрим на функцию загрузки шрифта:

Функция очень простая. Она просто загружает изображение на поверхность и устанавливает прозрачность. Устанавливать прозрачность (Color Keying) мы уже умеем. Следует только добавить, что здесь у нас используется белый цвет в качестве прозрачного (триплет 255,255,255 ). Теперь об ограничениях нашего шрифта. Буквы могут быть только английские и только в верхнем регистре. Собственно, диапазон шрифта от A до Z . Цифр и других символов нет. Теперь немного теории о кодировках.

Далее код функции для рисования текста. Посмотрите на него внимательно, попытайтесь понять что происходит, а ниже мы разберем ее подробно:

В качестве аргументов передаем поверхность с загруженным изображением, координаты куда выводить текст и сам текст. Далее в цикле выводим по порядку каждый символ строки:
for (i = 0; i < strlen(str); i++)

И наконец, как же это добро использовать. Вот кусок кода, использующий наши функции:

Все чрезвычайно просто. Вы можете доработать эту функцию, расширив диапазон символов в шрифте. Например, можно создать шрифт на 256 символов, а вместо служебных и непечатных символов оставить пустое место. Код получается абсолютно несложным. Вы можете создавать шрифты любых форм, гарнитур и размеров. Посмотрите исходный код программы bmf.cxx (Bitmap Font) и попробуйте разобраться в нем. А теперь рассмотрим следующий способ.

Также указываем вызывать функцию TTF_Quit() перед выходом из программы. Теперь посмотрите на код функции для вывода текста. Это очень просто.

Далее создаем поверхность, на которую отображаем текст при помощи загруженного шрифта:
SDL_Surface *sText = TTF_RenderText_Blended( fnt, message, color);

Функция TTF_RenderText_Blended() отображает сглаженный шрифт. Если вам нужно использовать шрифт без сглаживания, то используйте TTF_RenderText_Solid() с теми же самыми параметрами. Наконец, копируем надпись на поверхность, которую задали в аргументах (можно задать к примеру screen ), удаляем временную поверхность sText , чтобы очистить память и закрываем шрифт.

Из main() вызываем функцию для отображения текста:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

sdl2-KBD-мышь-Coords

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

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

знакомлюсь с программированием OpenGL с использованием SDL на Ubuntu с использованием c++. После некоторого осмотра и экспериментов я начинаю понимать. Мне нужен совет по обработке событий клавиатуры с SDL.

У меня есть камера 1-го лица и может ходить fwd, назад, стрейф влево и вправо и использовать мышь, чтобы посмотреть вокруг, что здорово. Вот моя функция processEvents:

теперь, пока это работает, у него есть некоторые ограничения. Самый большой и цель моего вопроса заключается в том, что он, похоже, процесс только последнюю клавишу, которая была нажата. Поэтому, если я держу "С", чтобы идти назад, и нажимаю "d", чтобы стрелять вправо, я в конечном итоге стреляю вправо, но не иду назад.

может ли кто-нибудь указать мне в правильном направлении для лучшей обработки клавиатуры с SDL, поддержки нескольких нажатий клавиш сразу и т. д.?

хорошим подходом будет написать обработчик клавиатуры ("input"), который будет обрабатывать входные события и сохранять состояние события в какой - то структуре (ассоциативный массив звучит хорошо-ключКак в графическом режиме вводить данные с клавиатуры sdl).

каждый раз, когда обработчик клавиатуры получает событие "клавиша нажата", он устанавливает ключ как включен (true), а когда он получает событие "клавиша вниз", он устанавливает его как отключено (false).

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

некоторый быстрый псевдо-код:

SDL отслеживает текущее состояние всех ключей. Вы можете получить доступ к этому состоянию через:

Итак, на каждой итерации вы можете обновлять движения на основе ключевого состояния. Чтобы сделать движение плавным, вы должны обновить величину движения на основе времени, прошедшего между обновлениями.

Если вы используете SDL2, используйте SDL_GetKeyboardState .

вместо того, чтобы смотреть только на события keydown, любое решение, которое будет заботиться о нескольких ключах сразу, должно будет смотреть как на события keydown, так и на события keyup и отслеживать состояние рассматриваемых ключей.

Итак, вместо (псевдокода):

вместо этого у вас будет что-то вроде (опять псевдокод):

тут updateMovement рутина будет смотреть на keystates и выяснить составное движение на основе состояния всех ключей движения вместе.

Читайте также: