Написал ремейк небольшой логической игрушки — «Полный квадра т». Код показался мне достаточно интересным чтобы описать на блоге.
По сюжету игры, ёжик перемещается по лабиринту из облаков. Ходить ёж умеет только по вертикали и горизонтали, а начав движение идет до тех пор, пока не упрется в пустоту (пройденные облака исчезают), край экрана или грозовую тучу. Необходимо выбрать начальную позицию для ежа и такой маршрут движения, чтобы все облака оказались пройдены.
В любой игре, чуть более интересной чем « «, используются анимации, проигрывается звук, поэтому следующие компоненты Qt затронуты в статье:
Игра состоит из нескольких экранов, которыми управляет ScreenController. Экраны я рисовал с использованием Qt Designer . Каждый игровой экран содержит кнопки, позволяющие перейти на другой экран, события от которых передаются контроллеру.
Логика игры вынесена в класс GameWidget , который загружает на графическую сцену блоки и как-то обрабатывает их сигналы. Например, если на сцене уже размещен ёжик и пользователь кликнул облачко, то GameWidget обеспечивает перемещение ежа в новую позицию при условии, что это не будет противоречить правилам игры.
WinScreen выводит информацию о победе и предлагает сыграть в игру еще раз.
При рисовании интерфейса в Qt Designer использованы самые обычные кнопки текстовые поля. Скругленные углы кнопок, цвет и размер рамки, изменение цвета при наведении и нажатии мыши получены за счет использования таблиц стилей Qt .
Установить таблицу стилей виджету (QWidget ) или приложению (QApplication ) можно методом setStyleSheet() . Для стилизации уже готового приложения можно передать таблицу стилей при запуске вместе с соответствующей опцией (-stylesheet style.qss ). Таблица стилей Qt являются надстройкой над каскадными таблицами стилей, используемыми при верстке веб страниц (CSS3 ) .
Ключевым понятием в QSS является селектор, т.е. элемент, к которому мы хотим применить стили, при этом, если некоторому объекту устанавливается таблица стилей, то стили будут распространяться также на все дочерние элементы. В качестве селектора могут выступать:
В игре стили применяются к объекту класса ScreenController , и автоматически будут распространены на все вложенные виджеты.
SetStyleSheet("* { background-color: rgba(176, 196, 222, 255); }" "QPushButton { " " background-color: rgba(255, 153, 102, 200); " " border-style: outset;" " border-width: 2px;" " border-radius: 10px;" " border-color: beige;" " font: bold 14px;" " width: 3em;" " padding: 6px;" "}" "QPushButton:hover {" "background-color: rgba(255, 102, 0, 200);" "}" "QPushButton:pressed {" "background-color: rgba(255, 0, 0, 200);" "}" "QPushButton:disabled {" "background-color: rgba(204, 153, 102, 200);" "}" "QTextEdit {" "background-color: rgba(102, 204, 102, 200);" " border-style: outset;" " border-width: 0px;" " border-radius: 10px;" " border-color: black;" " width: 3em;" " padding: 6px;" "}");
В примере задается цвет фона для всех виджетов, параметры кнопок и текстового поля, а также цвет кнопок, находящихся в определенных псевдосостояниях . Стиль, примененный для QPushButton:disabled будет распространен на все неактивные кнопки.
При использовании QSS необходимо заглядывать в документацию, чтобы проверить возможность стилизации свойств определенного типа виджета , кроме того, в документации описано огромное количество примеров .
Ежик плавно перемещается, за счет использования QPropertyAnimation, при этом сам ёж при перемещении машет лапками — проигрывается соответствующая .gif-анимация (QMovie) .
Любой элемент игры отображает какую-либо анимацию, поэтому в класс Block включены соответствующие поля и метод установки анимации.
Class Block: public QWidget { Q_OBJECT public: explicit Block(QWidget *parent = 0); void animation(QString texturename, bool randomStartFrame = false); protected: QMovie *m_animation; //!< анимация, проигрываемая блоком QLabel *m_label; //!< метка для отображения анимации }; Block::Block(QWidget *parent) : QWidget(parent), m_animation(new QMovie(this)), m_label(new QLabel(this)) { // ... m_label->setMovie(m_animation); m_animation->setCacheMode(QMovie::CacheMode::CacheAll); resize(BlockParam::BlockSize, BlockParam::BlockSize); m_animation->setScaledSize(size()); } // ... void Block::animation(QString texturename, bool randomStartFrame) { m_animation->stop(); m_animation->setFileName(texturename); if (randomStartFrame) m_animation->jumpToFrame(qrand() % m_animation->frameCount()); m_animation->start(); }
Класс блок агрегирует экземпляр QLabel, на котором и отображается анимация. QMovie поддерживает кеширование , которое по умолчанию отключено. При кешировании, в память помещается не следующий кадр, а пачка кадров, поэтому сокращаются затраты на их переключение. В приведенном фрагменте используется метод jumpToFrame() , устанавливающий текущий кадр, который не должен использоваться при включенном кешировании , однако в нашем случае он производит лишь установку начального кадра анимации и никогда не переключает кадры во время проигрывания.
Создайте новый проект.
Задайте папку, где будете хранить проект и имя самого проекта. Не допускайте в пути и имени русские буквы!
Выберите под какие архитектуры процессоров вы будете компилировать приложение.
Переходим на форму:
Перетаскиваем на форму кнопку и растягиваем ее.
Запускать на реальном устройстве проще, чем на виртуальном. Главное, чтобы вы включили отладку на телефоне, подключили его кабелем к компу, и чтобы на копме были драйвера на ваш телефон (на некоторые телефоны не нужны). Например, для Samsung устройств это делается через установку KIES. В общем, на тему подключения телефона аль планшета к компу для запуска Android приложений написано много статей.
У меня JIAYU G4 (для него дополнительные драйвера, например, не нужны). На разных устройствах разные могут стоят процессоры, и какую архитектуру выбрать не всегда понятно. Покажу, где это искать.
Я подключил телефон к компу. В Qt Creator выбираем первую попавшийся архитектуру.
И запускаем компиляцию приложения.
Появится окно выбора устройства для запуска приложения.
И там видим, что на моем телефоне запустить нельзя, так как на нем можно запускать приложения под архитектуру armeabi-v7a .
Значит, в настройках выбираем компиляцию под armeabi-v7a в режиме Release .
Запускаем.
И теперь наше устройство доступно для запуска приложения на телефоне:
Начнется компиляция apk файла, установка его на телефон и запуск приложения.
Процесс может быть не быстрым. Если вы увидели это:
то можете посмотреть, что на телефоне появилось. У меня вот это появилось.
Мы создали приложение и установили на телефоне! Обратите внимание, что наше приложение немного отличается от того, что мы создали в дизайнере форм по внешнему виду, и будет отличаться от того вида, которое мы увидим, если скомпилируем под Windows.
То есть, размеры кнопок и других элементов будут изменены. А чтобы и на компе и на телефоне приложение выглядели одинаково, нужно активно использовать разметку Layout, минимальные размеры компонентов и так далее. Но это уже из области верстки приложений.
Почему так сделано? Почему не компилируется так, чтобы приложение выглядело таким же как и на компе? Потому что Android устройства бывают разными, с разными разрешениями, пропорциями экрана. И жесткие размеры и положения элементов приведут к тому что на многих устройствах приложения не будут влазить в экран. В общем, фигня получится.
Теперь еще один момент. Лично я сохранил проект в папке D:\QtProjects :
И там появилась после компиляции папка с нашим сгенерированным приложением:
Зайдем в него и там в папку android-build , а там в папку bin :
И вот наш apk файл. Это и есть приложение под Android, которое вы можете распространять. К сожалению, минус Qt в том, что apk файл получается большим. У нас простое приложение с одной кнопкой весит 7Мб. Но это цена того, что мы создали приложение не в JAVA через Android Studio, например, на через Qt на С++.
Теперь запустим на виртуальном устройстве. Вот тут нас ждут танцы с бубном.
Щелкаем на кнопку для выбора системы под компиляцию.
Ждем, когда Qt всё настроит у себя внутри. Если ниже треугольник стал зеленым, то всё в порядке.
Нажимаем на него (на зеленый треугольник).
Если всё скомпилировалось удачно, то появится окно с выбором устройства для запуска приложения. Так как у меня еще и телефон подключен физически, то у меня виден телефон. У вас этого не будет (если только не подключите специально телефон аль планшет).
Выберете наше виртуальное устройство (оно должно быть в разделе Compatiable devises ).
Вот тут могут начать капризы! Если что-то пойдет не так, в процессе компиляции, то надо закрыть виртуальное устройство, возможно и Qt, возможно перезагрузить комп и попробовать скомпилировать и запустить! Возможно надо будет удалить папку с скомпилированным приложением.
Внизу в Qt Creftor стали появляться данные о компиляции и запуске приложения на виртуальном устройстве.
Внизу справа можно посмотреть на процент компиляции. Процесс не быстрый! Может занять несколько минут!
Если всё пойдет хорошо, то у вас на виртуальном устройстве запустится приложение, и всё будет ok. То есть вы запустили приложением, оно работает, в папке с скопилированным приложением в папке android-build , а там в папке bin найдете apk файл.
Дальнеший же текст предназначет для тех, у кого пошло что-то не так.
Иногда бывает так, что вы запускаете компиляцию вашего приложения, но виртуальное устройство не видится среди доступных:
Теперь оно в разделе Uncompatiable devises . Если мы по нему дважды щелкнем, то Qt Creator выдаст ошибку «When executing step “Deploy to Android device”»
Вначале проверьте платформу процессора, под которую вы компилировали, и платформу на виртуальном устройстве. Если они совпадают, то может помочь следующее:
С этой напастью разобраться просто. Идем в папку, где у вас хранится проект.
И удаляем ту папку, которой соответствует папка с скомпилированым приложением под ту архитектуру у процессора, под которую мы компилировали.
И пробуем опять запустить.
Итак, вы создали и запустили свое первое Android приложение, созданное на Qt.
Космос сам себя не наложит
Давно хотел сделать какой-нибудь проект под Android, а, как известно, основная масса проектов разрабатывается на Android SDK и Java, а NDK рекомендуют использовать только в “критичных по скорости” местах и не делать на нем все целиком.
Но кому нужны все эти рекомендации и правила, когда есть Qt? Java я не знаю в той степени, которую считаю достаточной для качественной разработки игры, и изучать мне ее не хотелось, зато у меня имеются в запасе знания C++. После нескольких тестовых проектов на Qt под Android я понял, что на нем вполне можно разработать полноценное приложение, да еще и перенести его на другие платформы. Так же, посмотрев видео Shia LaBeouf - Just Do it, стало понятно, что я обречен это сделать.
Итак, я хочу рассказать про опыт разработки игры под Android на Qt 5.5.1 и С++.
Внезапно, захотелось сделать игру про нечто, падающее в пещеру, контуры которой меняются со временем. Первоначально предполагалось сделать двухмерную игру с графикой в рисованном стиле. В дальнейшем все перетекло в трехмерную игру с видом сверху. Был написан генератор пещеры, который позволял создавать слои с контурами. Как рассчитывать столкновения с стенами пещеры и как превратить их в трехмерную модель? Можно было долго думать и выдумать что-нибудь невероятно классное, но я пошел обходным путем и сделал воксельную геометрию мира. Расчет столкновений и вывод на экран стали заметно проще, но ценой того, что игра стала похожа на майнкрафт. Я не растерялся и сделал её еще больше на него похожей, добавив модель персонажа из него же. Так и сформировался вид и концепция игры.
Первая версия генератора пещеры (архивное фото)
Приступая к разработке игры, я не ставил себе цель заработать на ней, как многие, а хотел просто начать свой проект и довести его до конца. Поэтому игра должна быть бесплатная (кто у меня ее купит?), но все-таки с минимальным количеством рекламы.
Экспериментируя с этими виджетами, я сделал несколько выводов:
Для реализации игры я выбрал QOpenGLWindow, а пользовательский интерфейс пришлось велосипедить самому.
Обновление кадров было реализовано по сигналу frameSwapped(), который генерируется после swapBuffers. Использование этого сигнала позволяет достичь большей плавности смены кадров, чем при использовании таймеров.
Для расчета анимации мне требовалось посчитать время кадра. Для этого я использовал сначала QTime , что было плохой идеей, так как этот класс считает немонотонное время, а на мобильном устройстве часто происходит корректировка времени, что приводило к попаданию в прошлое или будущее, в зависимости от ухода часов на устройстве. Также разрешение изменения этого класса ограничивается миллисекундами, что недостаточно для плавной анимации при нестабильном фпс.
Поразмыслив и обратившись к документации, я решил использовать класс QElapsedTimer , который старается использовать монотонное время и имеет разрешение до наносекунд.
Первый скриншот игры
В дальнейшем мы нарисовали оригинальные текстуры для нескольких уровней и сделали текстуры персонажей.
Процесс рисования “красивого” интерфейса и персонажей оказался довольно длительным. Пока дизайнер пытался выдавить из себя нового персонажа или кнопку, мне ничего не оставалось делать, кроме как продолжать оптимизировать код.
Скриншот из предпоследней версии
Проблема возникла в крайних пикселях блоков, которые являются смежными с другими блоками. При округлении текстурных координат стали появляться артефакты в виде полосок на краях блоков. Эту проблему я решил путем добавления каждому блоку окантовки шириной в один пиксель, дублирующую пиксель края блока. Такой своеобразный CLAMP_TO_EDGE.
К сожалению, при таком подходе я не смог использовать mipmap для уровня, т.к. текстурные координаты в вершинном буфере должны учитывать это смещение на один пиксель, а при создании текстуры уменьшенной детализации это смещение становится меньше, и мне бы пришлось использовать различную геометрию уровня в зависимости от степени детализации. Я решил с этим не заморачиваться, т.к. сама текстура уровня всего 256х256 пикселей, и особого выигрыша в производительности билинейная фильтрация не принесла бы, а принесла бы лишь дополнительные сложности в реализации.
Еще хотел заметить, что хотя блоков и всего 32, но в свойствах уровня я задал возможность расставлять блоки повернутыми на 90, 180 и 270 градусов, а также анимацию переключения между текстурой блока, что позволило разнообразить визуальную составляющую игры. Хотя, анимацию я применил только на одном из уровней для создания эффекта вращения вентиляторов.
Удобно то, что класс автоматически добавляет define таким образом, что шейдер ES компилируется нормально и на десктопе и на мобильном устройстве. Это относится в первую очередь к спецификаторам точности, которые на десктопе превращаются в ничто.
Мне пришлось написать отдельные шейдеры для игрового мира, включающие освещение и анимацию некоторых блоков, шейдер для персонажа и шейдеры интерфейса.
Шейдеры интерфейса включают в себя
Бар хп\щит
Этот бар я решил реализовать шейдером, сначала мне это показалось очень странной идеей, но в конце концов я ее принял как неизбежное и реализовал таким способом:
Код шейдера
#ifdef GL_ES
precision highp int;
#endif
varying highp vec4 v_position;
varying highp vec2 v_dim;
uniform lowp vec4 u_color;
uniform highp float u_tg;
uniform highp float u_value_a;
uniform highp float u_value_b;
uniform highp int u_step;
uniform lowp vec3 u_pallete;
void main()
{
int hstep = u_step/2;
int w = int(v_dim.x);
int h = int(v_dim.y);
int wd = u_step*3;
int pos_bl = int(v_position.x - u_tg*v_position.y + v_dim.y);
int pos_br = int(v_position.x + u_tg*v_position.y);
int pos_l = (pos_bl - wd*(pos_bl/wd))/u_step;
lowp float b0 = float(pos_l == 0) * float(pos_bl <= int(u_value_a*v_dim.x));
lowp float b1 = float(pos_l == 1) * float(pos_bl >= int((1.0-u_value_b)*v_dim.x));
lowp float b2 = clamp(float(pos_l == 2) + 1.0-(b0+b1), 0.0, 1.0);
highp float p = abs(2.0*(v_position.w - 0.5));
highp float out_p = (1.0 - 0.25*p);
lowp float i = float(int(v_position.y) > hstep) * float(int(v_position.y) < h - hstep);
lowp float o = (1.0-i)*float(pos_br >= h) * float(pos_bl <=w);
lowp float a = i*float(pos_br >= h+u_step) * float(pos_bl <=w - u_step);
lowp float b = i*float(pos_br < h+u_step) * float(pos_br >= h);
lowp float c = i*float(pos_bl > w - u_step) * float(pos_bl <= w);
highp float pr = (1.0 - p)*a;
gl_FragColor = vec4(u_pallete*pr*b0
+ u_pallete*pr*b1
+ u_pallete*pr*b2
+ u_pallete*out_p * b
+ u_pallete*out_p * c
+ mix(u_pallete, u_pallete, v_position.z)*out_p*o,
clamp(a+b+c+o, 0.0, 1.0)*u_color.a);
}
Итог всего этого - если вы планируете использовать шейдеры в мобильной игре, проверяйте их на самых распространенных моделях графических ускорителей. Если шейдер компилируется и работает у вас на компьютере, это еще не означает, что он будет работать на телефоне вашего соседа. Новый Vulkan API должен решить проблему с различными компиляторами шейдеров и привнеси порядок в этот безумный мир, но это дело будущего, а сегодня имеем то, что имеем.
Со сжатыми звуковыми файлами умеет работать только QMediaPlayer, но у этого класса, точнее, у его реализации под Android есть несколько неприятных моментов.
Все эти недостатки привели к тому, что после добавления звуков в игру появились ощутимые проседания FPS при воспроизведении звуков и музыки.
Решением стал отказ от этих классов и использованием для звуков библиотеки SFML . Очень простая и легковесная библиотека, похожая на SDL. Удобные классы для работы с графикой, звуком, устройствами ввода. Эта библиотека не умеет работать с mp3 (лицензия, все дела), но зато умеет многое другое. Я использовал для эффектов и музыки формат ogg.
Сперва был добавлен только один маленький баннер в меню, но в дальнейшем образовалось межэкранное объявление.
Занятно, что межэкранное объявление, находясь даже в загруженном состоянии, появляется с некоторой задержкой. То есть появилась необходимость блокирования пользовательского интерфейса в момент появления рекламы и восстановление после ее закрытия. При этом, библиотека не позволяла отловить моменты, когда объявление показано и закрыто. Данный функционал библиотеки я допилил в версию под Android. Версию под ios трогать пока не стал, за неимением возможности проверить работоспособность.
В события я вынес нажатие всех кнопок интерфейса, возникновение некоторых игровых ситуаций, открытия и разблокировки персонажей с уровнями.
Благодаря сбору всей этой статистики я могу сидеть за ноутбуком и наблюдать в реальном времени, как в Бразилии кто-то запустил игру, не смог пройти первую миссию, вышел и, вероятно, удалил игру.
Еще, если верить статистике,- мы сейчас чемпионы по нашей игре.
Чтобы полноценно разрабатывать приложение самому, необходимо как минимум иметь аккаунты AdWords, AdSense, AdMob, Google Analytics. При этом между ними устанавливается связь. Все эти аккаунты - отдельные продукты Google и имеют различную техническую поддержку и настройки. Также стоит заметить, что аккаунт AdMob требует наличия аккаунтов AdWords и AdSense. При этом все эти аккаунты могут быть привязаны в единственном экземпляре к основному аккаунту Gmail. Но, как показала практика, во всем этом можно запутаться с самого начала, потому что ты открываешь один сервис, он тебе предлагает создать новый аккаунт в другом, тот в третьем и так далее.
Я каким-то магическим образом так, что сотрудник техподдержки не смог объяснить произошедшее, создал 2 аккаунта AdWords и привязал их к одной почте, при этом привязав один аккаунт к консоли разработчика, а другой к AdMob (об этом я не знал).
На один аккаунт я закинул 500р, чтобы проверить рекламную кампанию. В попытках разобраться с этим и следуя советам техподдержки, я перенес один из аккаунтов на “левую” почту и закрыл сам себе доступ к нему. Все это привело сначала к неработоспособности обоих аккаунтов с моей почты, затем, при повторных отключениях и подключениях самого себя, работоспособность вернулась. Но, как выяснилось, перестал работать AdMob. Так как AdMob мне был важнее тех 500р, пришлось провести всю эту процедуру заново, попутно молясь о том, чтобы я не потерял доступ вообще ко всему, вернуть работу AdMob. И конечно, те 500р остались висеть на не подключенном аккаунте.
Так что, аккуратнее с этим.
Для осуществления переводов текстовой информации в Qt существует встроенный механизм, приводящийся в исполнения классом QTranslator myTranslator;
myTranslator.load(":/translations/neverfall_" + QLocale::system().name());
a.installTranslator(&myTranslator);
Все строки, которые необходимо перевести, передаются в функцию QObject::tr(), для классов, не являющихся наследниками QObject можно использовать функцию QApplication::translate и для строк, объявленных в массивах макросы QT_TRANSLATE_NOOP, QT_TR_NOOP.
Но это только полдела. Необходимо создать сами переводы, что производится программами lupdate и lrelease. Первая собирает информацию из исходного кода, содержащего эти функции и макросы, и создает Xml файл с информацией для перевода.
Вторая собирает из xml файла бинарный файл qm, который загружается непосредственно в
5 ответов
Я потратил более десяти лет на различные игры на C++, как на 2D, так и на 3D, для нескольких разных двигателей, больших и малых, и у меня также был короткий, но довольно интенсивный запуск с Qt5 (1,5 года на момент написания). Пока Qt сдул меня со всеми его аккуратно сложными кросс-платформенными и функциональными возможностями, и поэтому я планирую портировать свой крупнейший игровой проект на Qt, как только время позволит мне.
Честно говоря, я немного смутил себя тем, почему Qt не более распространен в играх. Я думаю, что основной причиной является его довольно кривая история лицензирования вместе с тем фактом, что она просто не продается для использования в играх. Qt, в конце концов, сделан главным образом для туза в кросс-платформенной графике UI + в реальном времени на многих платформах из встроенных и выше. Теперь, когда digia взяла верх и с новыми функциями QML/QtQuick, возможно, скоро появится бум Qt, кто знает? Я уверен, что больше разработчиков игр обнаружит Qt и начнет использовать его в своих проектах.
Чтобы ответить на ваш вопрос, я постараюсь сопоставить предложения Qt с потребностями разных типов игр.
В традиционном Qt существуют различные абстракции для графики. Для некоторых небольших встроенных платформ он может основываться только на простой 2D-подсистеме. Но для большинства настольных платформ (Windows/MacOSX/Linux) и мобильных платформ (Android/OSX) 2D-абстракция аккуратно опирается на высокопроизводительный 3D-стек на основе OpenGL или OpenGL ES соответственно.
Это настоящая жемчужина и делает графическое программирование радостью благодаря хорошо продуманной архитектуре, которая позволяет вам выбирать, как высоко или низкоуровневое вы хотите подходить к графическому программированию.
Существует множество классов, которые позволяют вам выполнять свой рисунок, как обычно, с известными понятиями, такими как цвет, толщина линии и форма, зная, что все это будет 3D ускорено под капотом.
Тогда появляется совершенно новая вещь "QtQuick" или "QML". Декларативный язык, который вместе с java script обеспечивает самый быстрый и самый скудный способ разыгрывать интерактивный интерфейс и игры, о которых я знаю на этой планете. После того, как мне удалось совершить полный полет клавиш фортепиано в 5 строках кода, и менее чем за 15 минут я был продан.
EDITED 23/2-17, чтобы быть более правильным. См. S.O. историю изменений, которые были изменены в этом разделе.
Qt традиционно имеет очень сильную связь с OpenGL, и эта связь имеет сервер Qt очень хорошо, так как OpenGL переносима и работает на широком спектре платформ. Однако с осознанием того, что OpenGL показывает возраст, постоянно возникающий вопрос о сопоставимости с DirectX на платформах Microsoft и появление новых технологий, таких как Vulkan, скрывается в ближайшем будущем, Digia сделала мудрый стратегический шаг, начиная с предварительное превентивное обобщение уровня абстракции оборудования в сторону графического оборудования. Итак, теперь Qt привязан к OpenGL, но вскоре он будет поддерживать многие другие графические абстракции, к вашей большой выгоде в качестве разработчика игр.
Пока мы ждем, в Qt также нет ничего, что помешало бы вам использовать DX вместе с Qt на платформах Microsoft. Qt подходит для того, чтобы не мешать другим библиотекам на любой платформе, поэтому он будет работать с множеством других наборов инструментов и движков, и вы можете даже встроить движки игр на основе OpenGL внутри Qt, открыв контекст Qt OpenGL напрямую. Также сохранение такой же кодовой базы для игры, которая портирована на две примечательные мобильные платформы с Qt, будет намного проще без DX.
Но помимо всех классов удобства для управления эффектами OpenGL, такими как VBO, FBO, загрузкой текстур и шейдеров и т.д., на самом деле нет полноценного 3D-движка в любом месте Qt.
ОБНОВЛЕНИЕ 2016-01-29: С тех пор как я впервые написал этот ответ, я пришел к выводу, что прилагаются большие усилия для обеспечения полномасштабного 3D-движка в Qt. Он называется Qt3D 2.0 и является полным переписанием старого Qt3D, который был частью Qt4.x и был частью только одного релиза, прежде чем он был удален из-за политических причин (Nokia отбросила Qt).
У этого есть внушительный набор особенностей, и много хорошего мышления пошло в это API, чтобы гарантировать, что это может использовать весь потенциал современного графического оборудования, сохраняя при этом гибкость и эффективность. Еще одна хорошая новость заключается в предварительном просмотре технологий. Это означает, что вы можете опробовать его сегодня, и он скоро станет частью основной линии Qt. Вы можете прочитать об этом .
Как часть 3D-стека, Qt имеет полный набор математических функций, таких как матрица, вектор, кватернионы, точка, прямоугольник и т.д.
Общие функции stl math, такие как sqrt, floor, sin и т.д., также обертываются в уровень независимости от платформы.
Нет поддержки для продвинутой математики, такой как полномасштабный физический движок, обнаружение столкновения или ответ.
Для этого вас может заинтересовать следующее:
Qt имеет полноценную систему управления ресурсами, которая компилирует ресурсы в ваш двоичный файл. Это кросс-платформа и поддерживает любой тип файла, который вам нужен, с особой поддержкой для общих форматов изображений, svg, звуков, шрифтов, HTML, CSS. И загрузка и использование ресурсов действительно просты, так как все Qt файлы handlign orutines принимают URL-адреса, указывающие на эти ресурсы. Действительно удивительный.
Код GUI - это Qt forte. Он имеет отличные инструменты для работы с графическими интерфейсами, что для некоторых небольших 2D-игр на самом деле можно использовать в качестве редакторов уровней.
ОБНОВЛЕНИЕ 2016-01-29: . Это часть основных значений для Qt как агностики платформы. Qt поддерживает основные настольные платформы, основные мобильные платформы и множество встроенных аппаратных средств, о которых вы никогда не слышали. Пожалуйста, ознакомьтесь с официальным списком поддерживаемых сообществом платформ (free/open source) . Это позволит вам принести свою основную неизмененную базу кодов на все платформы, которые вам нравятся, что сэкономит вам много времени, денег и усилий в тот день, когда вы решите сделать "версию iOS".
Qt завершает всю платформу интеграции кросс-платформенным способом. Это включает в себя:
Qt имеет полную структуру для работы с государственными машинами. Вдобавок к этому существует полная структура анимационных свойств, которые могут быть использованы для создания интерактивного интерфейса в 2D (или даже 3D, если вы правильно играете в карты). В нем есть все, что вы ожидаете, как облегчение, автоматический переход состояния и множество удобных оберток и способы делать интересные вещи. Это похоже на работу с jQuery, но на С++. Для некоторых игр это все, что вам нужно.
Qt имеет кучу STL-подобных контейнерных классов с расширениями для размещения специфических функций Qt. Эти классы включают в себя все: от списков до карт до массивов и буферов.
Строка string Qt является моей любимой на любом языке. Он имеет свои причуды, но он дает вам массу возможностей и функций, и, как обычно, кросс-платформу вместе со всеми ее друзьями:
Вся структура Qt реализована вокруг асинхронной архитектуры на основе циклов событий со светлыми событиями, называемыми "сигналы".
Qt поддерживает несколько уровней concurrency от потоков низкого уровня, через пулы управляемых потоков до современных сокращений карт и "фьючерсов". Он также имеет кросс-платформенный высокопроизводительный механизм блокировки, такой как мутации, блокировки, условия ожидания, блокировка, материал для атома и целая куча других вещей, которые у меня пока не получилось проверить.
Конечно, Qt имеет поддержку таймеров, которые хорошо вписываются во все это с множеством удобных функций, таких как настройка точности, запуск одного кадра и т.д.
Ввод с сенсорных экранов, мышей и клавиатур обрабатывается с использованием архитектуры событий, и Qt действительно имеет это завернутое в корзину. Qt совсем недавно (23/2-17) получил экспериментальную поддержку джойстиков и игровых приставок .
Существует также поддержка датчиков, таких как положение, давление, компас, вращение, температура, поэтому вы также можете делать клоны без клона.
И есть поддержка синего зуба для подключения и обмена игровыми данными по воздуху без доступа к Wi-Fi.
И есть поддержка камеры для того, что вы, возможно, захотите использовать в игре.
Все кросс-платформенные.
Qt имеет встроенный высокопроизводительный механизм ECMA (a.k.a. java script), привязанный к его ядру. О, и вы получите плотно встроенный порт входящего в комплект google веб-кит, если вам это нужно.
Qt обертывает gstreamer и другие медиа-библиотеки для поддержки воспроизведения мультимедийных файлов, таких как видео и звук. Это позволяет разработчику выбирать, на каком уровне они хотят взаимодействовать со средствами массовой информации. На высоком уровне вы можете просто поместить виджет и запустить.play() на низком уровне, вы получите доступ к буферам видео и аудио для удовольствия от обработки.
В зависимости от активного back-end Qt также дает вам доступ к кодированию потоков в сеть/диск и т.д.
С чего начать?
Внедрение интернационализации посредством использования ICU со всеми расширенными функциями, такими как поддержка RTL в текстовых виджетах и т.д.
Qt имеет подключаемую архитектуру. Это означает, что вы можете разбить исполняемый файл на биты и обновить их отдельно, перезагружая каждый бит динамически во время выполнения.
Qt имеет очень собственную структуру модульного тестирования, встроенную в нее. Этот пост становится длинным, поэтому я не буду вдаваться в подробности.
Qt имеет действительно хорошую документацию, и она постоянно совершенствуется. Если вы нажали некоторые из моих ссылок, которые вы уже знаете.
Qt был впервые выпущен в 1998 году и, таким образом, долгое время стабилизировался. Он имеет огромный набор регрессионных тестов, который запускается перед каждым выпуском, и он тщательно протестирован на множестве компиляторов, платформ и устройств. По какой-то причине это не входит в число многих списков разработчиков игр.
Это оказалось одним из чертовски длинного поста с большей частью Qt PRO, но я полагаю, что это то, что нужно, чтобы судить о платформе, прежде чем вы ее протестируете. Удачи вам в вашем проекте!
Новая большая MMORPG под названием Rift фактически выполняется с использованием Qt + DirectX. Это, по крайней мере, для меня первая крупномасштабная игра, которую я нашел, которая создана с Qt. Конечно, есть и DirectX, что не является большим сюрпризом. Жаль, потому что сам Qt будет мультиплатформенным, а DirectX - нет.
Итак, убедитесь, что Qt действительно очень хорошая платформа для любой разработки.