SFML — Урок 001. Подключение библиотеки SFML в проект на Qt
SFML представляет собой объектно-ориентированный аналог SDL. Библиотека предоставляет простой доступ к системам ввода вывода, аудио, сети передачи данных, а также к функционалу OpenGL.
А что если дополнительно прикрутить к этой библиотеке ещё и функционал Qt, получить в управление мощные возможности сигналов и слотов, ресурсных файлов Qt? Что для этого потребуется?
- Скачать с GitHub последнюю версию исходников SFML .
- Скомпилировать исходники в библиотеку
- Создать проект Qt
- Подключить библиотеку в проект
- Написать виджет, который будет рендериться напрямую через функционал SFML
- 1. Сборка SFML
- 2. Qt проект
- 3. Профайл проекта и main.cpp
- 4. widget.h
- 5. widget.cpp
- 6. qsfmlcanvas.h
- 7. qsqmlcanvas.cpp
Сборка SFML
Вообще, можно скачать предкомпилированные библиотеки SFML, но если у Вас будет компилятор, отличный от того, которым были собраны эти библиотеки, то соответственно ничего не заработает. Поэтому не будем экспериментировать, а сразу соберём библиотеку с тем компилтором, которым будем производить сборку проекта.
SFML представлен проектом с использованием системы сборки CMAKE, который без проблем открывается в Qt Creator.

Когда проект открыт, производим запуск CMAKE, а потом сборку самой библиотеки, как в режим Debug, так и в режим Release, чтобы иметь два комплекта бибилиотек.
В каталоге сборки будет каталог lib, в котором будет находится интересующие нас библиотеки. Их Мы добавим в проект на Qt, в котором будет использоваться SFML.
Будут собраны следующие библиотеки:
- smfl-audio
- sfml-graphics
- sfml-network
- sfml-window
- sfml-system
Qt проект
Далее создаём новый Qt проект. Создадим проект с использованием QWidget в качестве основного окна приложения. После того, как проект создан, добавьте в корень проекта каталог SFML, в котором будет содержаться две директории: lib и include.
В каталог lib необходимо поместить все скомпилированные бибилотеки SFML, как для debug версии, так и для release версии. А в каталог include необходимо поместить файлы из такого же каталога include, который находится в проекте исходников библиотеки SFML.
В результате структура данного каталога в вашем Qt проекте будет выглядеть следующим образом.

После того, как библиотека подготовлена, её необходимо подключить в Qt проект через pro файл.
Для этого пропишем следующие строки в pro файле:
$$PWD — означает местонахождение pro файла проекта, в котором мы прописываем конфигурацию проекта и подключаемые файлы. То есть все необходимые файлы библиотеки будем искать относительно pro файла проекта.
А теперь приступим к написанию самого проекта. Создадим SFML виджет, который будет помещаться внутрь основного виджета приложения, чтобы показать, что для использования SFML не обязательно отдавать всё окно приложения.
Структура проекта будет следующей:

Как видите, здесь имеется основной виджет окна Widget, а также имеется виджет qsqmlcanvas, в котором будет производиться работа библиотеки SFML. Также я добавил изображение, через ресурсный файл Qt. Да! Это возможно! Возможно использовать ресурсные файлы Qt в библиотеке SFML, просто потребуется написать несколько дополнительных строчек кода для правильного извлечения изображений из ресурсного файла.
А теперь приступим к созданию проекта с использованием Qt и SFML. Было решено сделать приложение, в SFML виджете которого будет крутиться логотип Qt.

Профайл проекта и main.cpp
Про подключение библиотеки в проект было сказано выше, а файл main.cpp не подвергается никаким изменениям, поэтому не будет акцентировать внимание на них.
widget.h
В этом проекте я не буду использовать графический дизайнер, поэтому вручную пропишем QGridLayout в заголовочном файле окна, в котором будет размещаться SFML виджет.
widget.cpp
А в конструкторе создадим QSFMLCanvas виджет и установим его размещение в окне приложения.
qsfmlcanvas.h
Разберём содержимое заголовочного класса SFML виджета.
Методы onInit() и onUpdate() являются опциональными и по сути вы можете назвать их как захотите, важно то, что потребуется первоначально добавить все необходимые объекты и периодически обновлять их.
А вот метод paintEngine() необходимо переопределить обязательно, поскольку мы не будем использовать движок отрисовки Qt, то этот метод должен будет возвращать nullptr.
Методы showEvent() и paintEvent() будут использоваться для инициализации функционала SFML и первоначальной отрисовки и обновления отрисовки объектов. Это методы, которые являются методами класса QWidget , от которого наследован класс SFML виджета. Перерисовка SFML виджета благодаря этим методам будем производиться в рамках инфраструктуры событий Qt. Что это значит? Дело в том, что метод paintEvent() может быть вызван вызовом метода repaint() , repaint() вызывает событие перерисовки в рамках стека вызовов Qt приложения, поэтому не стоит удивляться, что для перерисовки не производится прямого вызова метода paintEvent().
Также вы могли заметить, что в данном классе используется множественное наследование от двух классов: QWidget и sf::RenderWindow.
Наследование от QWidget нам необходимо, чтобы получить возможность внедрения SFML виджета в любое место интерфейса приложения, а также получить доступ к функционалу сигналов и слотов Qt, тогда как наследование от sf::RenderWindow необходимо для получения доступа к функционалу данной бибилотеки, плюс которой состоит в том, что она напрямую работает с OpenGL.
qsqmlcanvas.cpp
ВНИМАНИЕ: Проект создавался под KDE NEON 5.8.2 и является образцом, корректный запуск которого не гарантирован под другими ОС, в частности Вам потребуется сборка библиотеки SFML под вашу целевую платформу и с вашим компилятором.
Первый игровой движок на С++ и SFML

Прежде чем приступить к весёлой части с кодом, придётся пройти муторную, но важную часть с настройкой sfml. Данный гайд написан для Visual Studio 2019 на Windows. Установка для VS 2017 практически идентична, но могут быть незначительные отличия. Для других платформ крайне рекомендуется поискать гайд по настройке именно для вашего окружения. Ошибки на этом этапе, в лучшем случае, не дадут проекту скомпилироваться, в худшем – скомпилируются неправильно и вынесут вам мозг.
Переходим на главный сайт библиотеки и скачиваем последнюю стабильную версию (2.5.1 к моменту написания статьи). Выбираем для С++ 15(2017) 32-бита. Установка 64-битной версии идентична, для экономии времени сосредоточимся на более универсальной.
Распаковываем архив в удобную директорию, можно сразу сохранить в буфер путь до содержимого папки, в моем случае – это C:\SFML-2.5.1\ .
Открываем VS-2019, создаем новое консольное приложение Windows, Называем проект FirstGameEngine, получаем консольный хеллоуворлд.
Теперь включаем концентрацию на максимум, задача довольно простая, но почти каждый допускает ошибку во время первой настройки. Открываем вкладку Проект , в самом низу выбираем свойства: FirstGameEngine .

Выставляем конфигурацию Все конфигурации и платформу Win32 . Выбираем пункт С/С++ → Общие , находим Дополнительные каталоги включаемых файлов – здесь нужно указать путь до папки include . Вставляем путь из буфера и дописываем, как сделал я. Если сомневаетесь, нажмите изменить и найдите папку через эксплорер.

Спускаемся в Компоновщик → Дополнительные каталоги библиотек и проделываем тоже самое, но уже с папкой lib .

Переключаем Конфигурацию на Debug. Открываем Компоновщик → Ввод → Дополнительные зависимости . Копируем этот перечень sfml-graphics-d.lib;sfml-window-d.lib;sfml-system-d.lib;sfml-audio-d.lib; и аккуратно, не стирая и не перезаписывая уже имеющиеся записи, вставляем его в начало списка.

Переключаемся на Release и так же аккуратно вставляем sfml-graphics.lib;sfml-window.lib;sfml-system.lib;sfml-audio.lib;
Теперь поочередно запускаем Debug и Release, ловим по ошибке. Этот шаг необходим, чтобы студия создала папки проекта с exe-файлами. Сразу найдите эти каталоги. Их расположение зависит от настроек студии. Обычно они создаются на уровень выше папки с кодом. Теперь возвращаемся к распакованному архиву sfml, находим папку bin и копируем все бинарники с символом d в названии плюс openal32.bin в папку Debug, и то же самое без d + openal32.bin в Release.
Должна получиться такая картина:

Самая нудная часть позади.
Написание первого игрового движка на С++.
К файлу FirstGameEngine.cpp мы вернемся чуть позже. Его единственная задача – это запустить в функции main() наш движок.
Класс персонажа.
Bob – простой класс для представления фигурки персонажа, управляемой игроком. Код класса будет легко расширяться, а что самое главное – его несложно переписать под любой другой игровой объект, который вы захотите добавить. Для этого потребуется заменить текстуру и описать поведение нового объекта в методе update().
Создаем новый заголовочный файл. Кликаем Проект → Добавить новый элемент → Файл заголовка. Называем Bob.h и объявляем следующие поля и методы:
Здесь мы объявили поля типа Texture и Sprite. Дальше мы свяжем их, и любое действие на экране с объектом Sprite будет сопровождаться изображением Боба:

Сохраните это изображение в директорию FirstGameEngine/FirstGameEngine.
Bob.cpp
Приступим к реализации.
По той же схеме создаем файл Bob.cpp, только выбираем Файл С++ . Теперь добавляем в файл код:
В конструкторе мы установили значение переменной m_Speed на 400. Это значит, что Боб пересечет экран шириной в 1920 пикселей за 5 секунд. Также мы загрузили файл Bob.png в Texture и связали его с объектом Sprite. В переменных m_Position.x и m_Position.y установлено начальное положение Боба. Не забывайте, что в С++ координаты отсчитываются от верхнего левого угла и ось-у направлена вниз, не потеряйте Боба.
Функция update обрабатывает два If. Первое If проверяет, нажата ли правая кнопка (m_RightPressed), а второе следит за левой (m_LeftPressed). В каждом If скорость (m_Speed) умножается на elapsedTime. Переменная elapsedTime рассчитывается в функции Start движка (класс Engine). Им мы сейчас и займемся.
Engine.h
Создаем новый заголовочный файл Engine.h:
Класс библиотеки SFML, RenderWIndow, используется для рендера всего, что есть на экране. Переменные Sprite и Texture нужны для создания фона. Также в заголовке мы объявили экземпляр класса Bob.
Engine.cpp
Здесь мы реализуем конструктор и функцию start(). Создаем файл класса так же, как для Bob.cpp, и добавляем в него код:
Конструктор получает разрешение экрана и разворачивает игру на весь экран с помощью m_Window.create, загружается Texture и связывается с объектом Sprite.
В качестве фона вы можете использовать любое изображение, ниже я выложу своё. Рекомендую подобрать или масштабировать его по размерам вашего рабочего стола. Пункт не критичный, но смотрится приятнее, а в рамках данного курса мы не будем разбирать работу с окном и его размерами. Переименуйте файл в background.jpg и поместите в каталог FirstGameEngine/FirstGameEngine .
Можете воспользоваться моим примером:

Игровой цикл.
Следующие три функции будут описаны каждая в отдельном файле, но при этом они должны быть частью Engine.h. Поэтому в начале каждого файла укажем директиву #include «Engine.h», так что Visual Studio будет знать, что мы делаем. Это делается для удобства дальнейшего масштабирования проекта.
Обрабатываем пользовательский ввод
Функция input обрабатывает нажатия клавиш через константу Keyboard::isKeyPressed, предоставляемую SFML. При нажатии Escape m_Window будет закрыто. Для клавиш A и D вызывается соответствующая функция движения.
Обновляем игровые объекты
Теперь опишем функцию update. Её задача вызвать аналогичную функцию обновления состояния у всех игровых объектов. В нашем случае это только Bob.
Создаём файл Update.cpp и добавьте в него код:
Отрисовка экрана.
Это последняя функция класса Engine, её задача – отрисовать все объекты текущего экрана. Создайте файл Draw.cpp и добавьте в него код:
Экран каждый виток цикла очищается методом clear. Первым делом должен быть отрисован фон, чтобы потом поверх него можно было поместить Боба.
Запускаем движок!
Теперь вернемся к FirstGameEngine.cpp.
Наш игровой движок, как и положено первой работе, получился очень простым: он умеет только двигать главный объект и закрывать программу. Он не умеет обрабатывать столкновения, работать с интерфейсом и еще много чего. Возможно, этим мы займемся позже. Однако он отлично описывает то, как строится ядро игрового проекта с нуля. К тому же, в него довольно легко добавлять новые объекты и расширять функционал. Попробуйте, в качестве практики, добавить второго боба, управляемого клавишами J и L, у вас уже есть для этого все необходимые знания. Или поменяйте фон, если Боб выходит за границу экрана. Задачка уже посложней, но тоже вам по силам. =)
Графическая библиотека SFML в Linux: как ее установить и использовать
В операционной системе Linux, нередко, используется так называемая консоль. Это когда черный экран, командная строка и… все. Но, консоль бывает удобна, как правило, для обслуживания самой операционной системы, тогда как пользовательские приложения обычно используют графический интерфейс (так называемый GUI — Grafic User Interface). Для его реализации необходима, соответственно, та или иная графическая библиотека.
Вообще, в настоящее время графических библиотек просто масса – и больших и малых, и простых и многофункциональных, и т.д. Мы в этой не будем даже пытаться рассмотреть их все, а сосредоточимся на известной библиотеке SFML. Написано о ней достаточно, например, в Википедии.
По умолчанию, эта библиотека не является установленной в Linux (например, Ubuntu). Кроме того, не установлены и зависимости, требуемые для ее полноценной установки и работы.
Устанавливаем зависимости
Для установки зависимостей, равно как и для установки самой библиотеки, можно использовать команды apt-get , aptitude .
Настоятельно рекомендуется использовать именно aptitude , так как именно она позволяет установить зависимости корректно и без ошибок. Тогда как apt-get иногда не приводит к нужному результату.
Для того, чтобы установить зависимости, следует выполнить следующие команды:
- # sfml-window
- aptitude install libx11-dev -y
- aptitude install libxcb1-dev -y
- aptitude install libx11-xcb-dev -y
- aptitude install libxcb-randr0-dev -y
- aptitude install libxcb-image0-dev -y
- aptitude install libxrandr-dev -y
- aptitude install libgl1-mesa-dev -y
- aptitude install libudev-dev -y
- aptitude install libxrandr-dev -y
- # sfml-graphics
- aptitude install libfreetype6-dev -y
- aptitude install libjpeg-dev -y
- # sfml-audio
- aptitude install libopenal-dev -y
- aptitude install libflac-dev -y
- aptitude install libvorbis-dev -y
Например, в Ubuntu 16.04 LTS установка проходит без каких-либо проблем.
Устанавливаем библиотеку SFML (в Ubuntu, Debian)
Устанавливать библиотеку SFML на Linux можно по-разному:
Лучше всего выбрать первый способ, если есть возможность. Для этого используем команду
- sudo aptitude install libsfml-dev
Как компилировать программу с библиотекой SFML
Пример программного кода
Рассмотрим простейший пример:
// Подключаем заголовок модуля Graphics, а он автоматически подключает заголовок модуля Window
- #include <SFML/Graphics.hpp>
- int main()
- <
- // создаём окно
- sf::RenderWindow app(sf::VideoMode(800, 600, 32), "Hello World — SFML");
- // основной цикл
- while (app.isOpen())
- <
- // проверяем события (нажатие кнопки, закрытие окна и т.д.)
- sf::Event event;
- while (app.pollEvent(event))
- <
- // если событие "закрытие окна":
- if (event.type == sf::Event::Closed)
- // закрываем окно
- app.close();
- >
- // очищаем экран и заливаем его синим цветом
- app.clear(sf::Color(0,0,255));
- // отображаем на экран
- app.display();
- >
- return 0;
- >
1. Вначале следует создать объектный файл
- g++ -c main.cpp
Если все успешно, создастся файл main.o .
2. Сборка
Чтобы получить исполняемый файл, следует сделать сборку, т.е. связать скомпилированный файл с библиотекой SFML. SFML состоит из пяти модулей: system , window , graphics , audio и network и библиотек для каждого из них. Что бы собрать приложение с библиотекой SFML, нужно должны добавить опцию " -lsfml-xxx " к команде компоновки. Например, " -lsfml-graphics " для модуля graphics (префикс « lib » и расширение " .so " библиотеки должны быть опущены).
- g++ main.o -o sfml-app -lsfml-graphics -lsfml-window -lsfml-system
Если все будет нормально скомпилировано и собрано, то, будучи запущенной, эта программа выводит окно, залитое синим цветом, как на рисунке:

Запуск программы может производиться либо из консоли ( ./sfml-app ), либо путем двойного клика мыши на имени файла sfml-app в менеджере файлов.