
От переводчика: данная статья является десятой в цикле переводов официального руководства по библиотеке SFML. Прошлую статью можно найти тут. Данный цикл статей ставит своей целью предоставить людям, не знающим язык оригинала, возможность ознакомится с этой библиотекой. SFML — это простая и кроссплатформенная мультимедиа библиотека. SFML обеспечивает простой интерфейс для разработки игр и прочих мультимедийных приложений. Оригинальную статью можно найти тут. Начнем.
Оглавление:
0.1 Вступление
1. Приступая к работе
2. Модуль System
3. Модуль Window
4. Модуль Graphics
5. Модуль Audio
6. Модуль Network
1. Приступая к работе
- SFML и Visual Studio
- SFML и Code::Blocks (MinGW)
- SFML и Linux
- SFML и Xcode (Mac OS X)
- Компиляция SFML с помощью CMake
2. Модуль System
3. Модуль Window
- Открытие и управление окнами
- Обработка событий
- Работа с клавиатурой, мышью и джойстиками
- Использование OpenGL
4. Модуль Graphics
- Рисование 2D объектов
- Спрайты и текстуры
- Текст и шрифты
- Формы
- Проектирование ваших собственных объектов с помощью массивов вершин
- Позиция, вращение, масштаб: преобразование объектов
- Добавление специальных эффектов с шейдерами
- Контроль 2D камеры и вида
5. Модуль Audio
- Проигрывание звуков и музыки
- Запись аудио
- Пользовательские потоки аудио
- Спатиализация: звуки в 3D
6. Модуль Network
- Коммуникация с использованием сокетов
- Использование и расширение пакетов
- Веб-запросы с помощью HTTP
- Передача файлов с помощью FTP
Вступление
В этой статье приводится подробный список событий и объясняется, как эти события обрабатывать.
Тип sf::Event
До детального разбора обработки событий важно понять, что из себя представляет тип sf::Event, и как правильно использовать его. sf::Event состоит из объединения, хранящего в себе тип события, и вспомагательных функций и членов. Доступному члену объединения соответсвует один или несколько членов класса, например,
event.key соответствует событию KeyPressed. Попытка обработки любых других членов приведет к неопределенному поведению. Никогда не пытайтесь обработать не произошедшее событие.Экземпляр sf::Event можно инициализировать функцией
pollEvent (или waitEvent) класса sf::Window. Только эти две функции могут инициализировать экземпляр sf::Event. Для ясности, вот как выглядит типичный цикл обработки событий:
sf::Event event; // пока есть события, обрабатывать их... while (window.pollEvent(event)) { // проверяем тип события... switch (event.type) { // закрытие окна case sf::Event::Closed: window.close(); break; // нажатие клавиши case sf::Event::KeyPressed: ... break; // мы не обрабатываем другие типы событий default: break; } }
Перечитайте параграф выше и убедитесь, что вы все поняли. Класс sf::Event вызывает много проблем у начинающих программистов.
Ладно, теперь мы знаем, как события представлены в SFML, настало время выяснить, что каждое событие означает.
Событие Closed
Событие
sf::Event::Closed срабатывает, когда пользователь хочет закрыть окно, используя любой из методов, предоставляемых менеджером окон (кнопка закрытия, макросы клавиатуры и так далее). Это событие предоставляет информацию о том, что пользователь попытался закрыть окно; оно еще не закрыто.Обычно, в ответ на это событие, код вызывает
window.close(), чтобы закрыть окно. Однако, вы можете сделать еще что-то, например, сохранить текущее состояние приложения или спросить пользователя, что надо сделать. Если вы ничего не сделаете в ответ на это событие, окно будет оставаться открытым.Член класса, ассоциируемый с этим событием, не существует.
if (event.type == sf::Event::Closed) window.close();
Событие Resized
Событие
sf::Event::Resized срабатывает, когда происходит изменение размера окна. Либо в результате действия пользователя, либо программно, после вызова window.setSize.Вы можете использовать это событие, чтобы отрегулировать настройки отображения: область просмотра, если вы используете OpenGL напрямую, или текущую точку обзора, если вы используете
sfml-graphics.Член класса, ассоциируемый с этим событием, называется event.size и содержит новый размер окна.
if (event.type == sf::Event::Resized) { std::cout << "new width: " << event.size.width << std::endl; std::cout << "new height: " << event.size.height << std::endl; }
События LostFocus и GainedFocus
События
sf::Event::LostFocus и sf::Event::GainedFocus срабатывают, когда окно потеряло/приобрело фокус; это происходит, когда пользователь меняет текущее активное окно. Когда окно теряет фокус, оно не получает события клавиатуры.Это событие можно использовать, например, для приостановки игры, когда окно неактивно.
Член класса, ассоциируемый с этим событием, не существует.
if (event.type == sf::Event::LostFocus) myGame.pause(); if (event.type == sf::Event::GainedFocus) myGame.resume();
События TextEntered
Событие
sf::Event::TextEntered срабатывает, когда происходит ввод символа. Это не событие KeyPressed: TextEntered срабатывает, когда пользователь вводит символ, который может быть выведен. Например, нажатие '^' и 'e' на французской клавиатуре приведет к двум событиям KeyPressed и только к одному TextEntered, содержащему символ 'ê'. Это работает для всех методов ввода, предоставленным операционной системой.Это событие обычно используется для отлова пользовательского ввода в текстовое поле.
Член класса, ассоциируемый с этим событием, называется
event.text и содержит номер символа Unicode введенного символа. Вы можете поместить это значение в sf::String, или привести его к типу char после того, как убедитесь, что этот символ лежит в диапазоне ASCII символов (0 — 127).if (event.type == sf::Event::TextEntered) { if (event.text.unicode < 128) std::cout << "ASCII character typed: " << static_cast<char>(event.text.unicode) << std::endl; }
Многие программисты используют событие
KeyPressed для обработки пользовательского ввода и применяют сумасшедшие алгоритмы для обработки пользовательского ввода, которые пытаются интерпретировать все возможные комбинации клавиш. Не делайте этого!События KeyPressed и KeyReleased
События
sf::Event::KeyPressed и sf::Event::KeyReleased срабативают, когда клавиша на клавиатуре нажата/отжата. Если клавиша зажата, события
KeyPressed будут генерироваться с определенным интервалов, заданным операционной системой (т.е. та же задержка, что применяется, когда вы вводите текст в редакторе). Чтобы отменить повторение событий KeyPressed, вы можете вызвать window.setKeyRepeatEnabled(false). Очевидно, что событие KeyReleased никогда не повторяется.Эти события можно использовать, если вы хотите вызвать какое-нибудь действие ровно один раз, когда клавиша нажата или отжата, например, чтобы заставить персонажа прыгнуть.
Иногда люди пытаются использовать событие
KeyPressed для реализации плавного движения. Это не приводит к ожидаемому эффекту, потому что это событие генерируется с определенным интервалом. Чтобы реализовать плавное движение с помощью событий, вы должны использовать логическое значение, устанавливаемое KeyPressed и обнуляемое KeyReleased; движение должно осуществляться, пока это логическое значение установлено.Другие (более простые) пути реализации плавного движение, с использованием вода с клавиатуры с помощью sf::Keyboard (смотрите посвященную этому статью).
Член класса, ассоциируемый с этим событием, называется
event.key и содержит код нажатого/отжатого символа, а также текущее состояние клавиш-модификаторов (alt, control, shift, system).if (event.type == sf::Event::KeyPressed) { if (event.key.code == sf::Keyboard::Escape) { std::cout << "the escape key was pressed" << std::endl; std::cout << "control:" << event.key.control << std::endl; std::cout << "alt:" << event.key.alt << std::endl; std::cout << "shift:" << event.key.shift << std::endl; std::cout << "system:" << event.key.system << std::endl; } }
Помните, что некторые клавиши имеют специфичное значение для операционной системы, обработка этих клавиш приводит к неопределенному поведению. Например, клавиша F10 в Windows, которая меняет фокус, или клавиша F12, которая запуска дебагер при использовании Visual Studio. Эта проблема будет решена в будущих версиях SFML.
Событие MouseWheelMoved
Событие
sf::Event::MouseWheelMoved устарело и было упразнено в SFML 2.3. Используйте MouseWheelScrolled. Событие MouseWheelScrolled
Событие
sf::Event::MouseWheelScrolled вызыватеся, когда колесо мыши двигается вверх, вниз или вбок (если это поддерживается мышью). Член класса, ассоциируемый с этим событием, называется
event.mouseWheelScroll и содержит число тиков, на которое сместилось колесо, ориентацию движения колеса и текущую позицию курсора мыши.if (event.type == sf::Event::MouseWheelScrolled) { if (event.mouseWheelScroll.wheel == sf::Mouse::VerticalWheel) std::cout << "wheel type: vertical" << std::endl; else if (event.mouseWheelScroll.wheel == sf::Mouse::HorizontalWheel) std::cout << "wheel type: horizontal" << std::endl; else std::cout << "wheel type: unknown" << std::endl; std::cout << "wheel movement: " << event.mouseWheelScroll.delta << std::endl; std::cout << "mouse x: " << event.mouseWheelScroll.x << std::endl; std::cout << "mouse y: " << event.mouseWheelScroll.y << std::endl; }
События MouseButtonPressed и MouseButtonReleased
События
sf::Event::MouseButtonPressed и sf::Event::MouseButtonReleased срабатывают, когда кнопка мыши нажата/отпущена.SFML поддерживает 5 кнопок мыши: левую, правую, среднюю (колесо мыши), экстра #1 и экстра #2 (кнопки на боковой стороне).
Член класса, ассоциируемый с этим событием, называется
event.mouseButton и содержит код нажатой/отжатой кнопки, а также позицию курсора мыши.if (event.type == sf::Event::MouseButtonPressed) { if (event.mouseButton.button == sf::Mouse::Right) { std::cout << "the right button was pressed" << std::endl; std::cout << "mouse x: " << event.mouseButton.x << std::endl; std::cout << "mouse y: " << event.mouseButton.y << std::endl; } }
Событие MouseMoved
Событие
sf::Event::MouseMoved срабатывает, когда курсор мыши движется внутри окна. Это событие срабатывает, даже если окно не в фокусе. Однако, срабатывание происходит только когда курсор мыши движется только в пределах внутренней области окна (во внутреннюю облась окна не входят заголов и границы),
Член класса, ассоциируемый с этим событием, называется
event.mouseMove и содержит позицию курсора мыши относительно окна.if (event.type == sf::Event::MouseMoved) { std::cout << "new mouse x: " << event.mouseMove.x << std::endl; std::cout << "new mouse y: " << event.mouseMove.y << std::endl; }
События MouseEntered и MouseLeft
События
sf::Event::MouseEntered и sf::Event::MouseLeft срабатывают, когда курсор мыши входит в облась окна или покидает ее.Член класса, ассоциируемый с этим событием, не существует.
if (event.type == sf::Event::MouseEntered) std::cout << "the mouse cursor has entered the window" << std::endl; if (event.type == sf::Event::MouseLeft) std::cout << "the mouse cursor has left the window" << std::endl;
События JoystickButtonPressed и JoystickButtonReleased
События
sf::Event::JoystickButtonPressed и sf::Event::JoystickButtonReleased срабатывают, когда кнопка геймпада нажата/отжата. SFML поддерживает 8 джойстиков и 32 кнопки.
Член класса, ассоциируемый с этим событием, называется
event.joystickButton и содержит идентификатор джойстика и индекс нажатой/отжатой кнопки.if (event.type == sf::Event::JoystickButtonPressed) { std::cout << "joystick button pressed!" << std::endl; std::cout << "joystick id: " << event.joystickButton.joystickId << std::endl; std::cout << "button: " << event.joystickButton.button << std::endl; }
Событие JoystickMoved
Событие
sf::Event::JoystickMoved срабатывает, когда стик геймпада движется.Стики джойстика, как правило, очень чувствительны, именно поэтому SFML использует порог обнаружения, чтобы избежать постоянных срабатываний
JoystickMoved. Это пороговое значение можно изменить с помощью вызова функции Window::setJoystickThreshold.SFML поддерживает 8 стиков джойстика: X, Y, Z, R, U, V, POV X и POV Y. Как происходит взаимодействие с геймпадом зависит от драйвера этого геймпада.
Член класса, ассоциируемый с этим событием, называется
event.joystickMove и содержит идентификатор джойстика, имя стика и его текущую позицию (в интервале [-100, 100]).if (event.type == sf::Event::JoystickMoved) { if (event.joystickMove.axis == sf::Joystick::X) { std::cout << "X axis moved!" << std::endl; std::cout << "joystick id: " << event.joystickMove.joystickId << std::endl; std::cout << "new position: " << event.joystickMove.position << std::endl; } }
События JoystickConnected и JoystickDisconnected
События
sf::Event::JoystickConnected и sf::Event::JoystickDisconnected срабатывают, когда джойстик присоединяется/отсоединяется.Член класс, ассоциируемый с этим событием, называется
event.joystickConnect и содержит идентификатор присоединенного/отсоединенного джойстика.if (event.type == sf::Event::JoystickConnected) std::cout << "joystick connected: " << event.joystickConnect.joystickId << std::endl; if (event.type == sf::Event::JoystickDisconnected) std::cout << "joystick disconnected: " << event.joystickConnect.joystickId << std::endl;
Следующая статья: Работа с клавиатурой, мышью и джойстиками.
