Как стать автором
Обновить

2D-платформер от Qt 5.2 до Qt 5.4

Время на прочтение6 мин
Количество просмотров21K
image Привет, Хабр. Эта статья должна была быть написана еще зимой, но по объективным причинам пишу ее сейчас.

Решил я как-то год назад заняться ГеймДевом. Поздновато, конечно, но история не об этом. Сразу решил, что надо писать для мобильных устройств. Направление перспективное и для меня оказалось очень интересным.

Поскольку я программлю на С++, значит, надо подобрать кроссплатформенную среду разработки. Выбор пал на Qt. Сейчас точно не скажу, почему именно она, но выбор был сделан, да и история не об этом.

Достал книгу на русском, Внимательно прочитал половину, сделал детскую игру «Быки и Коровы». Здесь не о чем говорить, это был тестовый проект.

Почитал еще, обнаружил, что у Qt очень хорошая документация на родном сайте и в ней легко найти описание необходимых объектов. И это не может радовать.

Теперь стал вопрос о том, чтобы сделать проект немного посерьёзней. Везде советуют начинающим браться сначала за что-то простое, так сказать попробовать, научиться на своих ошибках и т.д. Я уже начал подготавливаться, чтобы написать старую и всем знакомую Lines, но вот тут стала необходимость для одного проекта написать что-нибудь на Android. И так родилась идея написать платформер. И вот, собственно говоря, история как раз об этом.

Решено было писать на С++, хотелось посмотреть, насколько адекватно оно будет потом работать на Android.
И сразу определился, что писать буду с использованием графической библиотеки Qt, потому что по ней достаточно много хорошего мануала, как говорилось раньше. Я не собираюсь описывать процесс создания платформера, этого добра в мировой сети достаточно на разных языках.

Начал писать это чудо в конце сентября на Qt 5.2, знаю, что уже была 5.3, но лень было заниматься обновлением. В начале ноября всё уже было готово, но по определённым причинам, мероприятие, для которого игра писалась, не состоялось и было перенесено на весну. Выкладывать для мира проект раньше времени нельзя. Было достаточно времени поработать над мелкими доработками и перенести её в Qt 5.4.

Кратко процесс реализации описал, теперь, собственно говоря, с какими проблемами я столкнулся во время разработки и переходом от одной версии к другой.

Графическая библиотека:

Графическая библиотека
Начнём с косяков.
Нативная библиотека Qt кушает очень много памяти. Пользовался компонентом QImage. При загрузке в память картинки размером 780 байт объём используемой памяти увеличивался не на пару килобайт, а на пару десятков, а иногда и сотен килобайт. Данный факт меня не очень радовал, а иногда раздражал.

Чтобы как-то уменьшить объемы используемой памяти, все графические элементы поместил в один файл. Но это было связанно еще и с удобством использования. Объем используемой памяти сразу уменьшился на 10М.

Второе, что бросилось в глаза, Это насколько сильно грузится процессор. Не 100%, но более 50%. Может, для игр это и нормально, но дальше было интересней.

При выходе Qt 5.4 компания-разработчик утверждала, что они улучшили графическую библиотеку.
Я подтверждаю, что-то они улучшили :). При переносе на 5.4 стало еще меньше использоваться оперативной памяти и процессор уже загружен был менее, чем на 50%. Эти все параметры смотрел в Windows, как дела обстоят на андроиде — не в курсе.

В процессе обнаружился еще один интересный факт с Зумом.
Стандартный размер экрана для моей игры — 540х960. Он единственный. При уменьшении картинки проблем никаких не возникало, даже начинало работать чуть пошустрее. А вот при увеличении были выявлены некоторые проблемы.

Во-первых — гладкого масштабирования не получилось, процесс отрисовки сразу увеличивался в 20-30 раз. Но от этого можно и отказаться, не такой уж это серьёзный проект, где надо много внимания уделять графике. Но для себя отметил, что надо готовить картинки для разных разрешений экрана.

Вторая проблема заключалась в следующем. Как ранее говорилось, все графические элементы были помещены в один файл. Надо было просто указать область, которую перерисовать на игровой экран. При увеличении данной области почему-то захватывался на 1 пиксель больше указанного.

Решением проблемы является то, что между элементами надо оставлять немного свободного места в 1-2 пикселя. Или сами элементы делать чуть меньшего размера, чем сама область. У меня получился 2-й вариант.

И последнее, что мне не понравилось. Это отсутствия возможности работать с картинками с маленькой цветовой гаммой (16 и 256). В QIMage реализовано якобы 256 бит, но каждый бит надо прописать заранее.

В остальном библиотека меня порадовала. Удобно с ней работать, поддерживает разные форматы картинок, можно сохранить полученное изображение на диск. Разнообразный размер инструментов


Работа со звуком

Работа со звуком
В книге описана работа с мультимедиа для версии 4.8. Но с тех пор всё поменялось. И компоненты, и работа с ними. Немного гугления и чтения документации привели к успеху. В итоге оказалось всё не так сложно. Описывать подробно не стану, на сегодня этой инфы достаточно на форумах и документация есть. Но если кому лень разбираться, пишите, отвечу.

Собственно говоря, с какими проблемами столкнулся. Файлы WAV больших размеров не терпят. Больших — имеется в виду дольше 3-х сек. MP3-файлы тоже не особо жалует. Более 5MB не получилось подключить. И не хотело собираться, когда итоговый размер медиа был более 10MB. Может, это ограничение как-то и регулируется, но я не нашел, как. Я уменьшил качество аудио MP3 файлов и всё пошло.

В остальном компоненты по управлению звуками работали достойно. Можно управлять уровнем громкости, MUTE'ировать звук без остановки аудио. Пускать музыку/звуки на фоне, не останавливая основной поток воспроизведения. Только если вы запустили в отдельном потоке звук, то он будет звучать, пока не закончится, и остановить принудительно его нельзя.

Еще столкнулся с проблемой в 5.2 — не работали внешние кнопки регуляции уровня звука. Пришлось допиливать Activity. О том, как я это делал, на Хабре статью написал. В версии 5.4 уже всё работает, ничего допиливать не надо.


Тачскрин

Тачскрин
Вот тут у меня самое большое недоразумение случилось. А суть заключается в следующем.

В версии 5.2 я изучил подробно работу с событиями тачскрина. Есть контейнер, который хранит координаты и состояние всех «пальцев» на экране. Есть события, которые реагируют на первое прикосновение (первый «палец»), событие на изменение (передвижение «пальцев» или изменение их количества на экране), и событие, которое сообщает о завершении тача (когда все «пальцы» убираются с экрана).

По сути, если у Вас в приложении будет использоваться мультитач, то события мышки можно даже и не обрабатывать. Всё прекрасно работает на событиях Тачскрина. Но по определённым надобностям мне пришлось обрабатывать и события мышки. Впоследствии это мне и помогло разобраться в проблемах.

Всё изменилось с версией 5.4. Когда я собрал на новом Qt проект и сел протестировать новый функционал, каково было моё удивление, когда обнаружил, что управление полетело. А произошло следующее.

Зачем-то разработчики Q, поменяли логику работы событий тачскрина и мышки! Теперь это работает как-то по-чудному. При первом касании «пальца», генерируются события MouseButtonPress и TouchBegin. Но потом, когда генерируется событие MouseMove а TouchUpdate не генерируется. Но в контейнере тача точка остаётся, но координата и состояние ее не меняется. И когда генерируется событие MouseButtonRelease, событие TouchEnd не генерируется и получается, что виртуально у вас всегда на экране «висит» один «палец».
Эта проблема решается следующим образом: при событии TouchBegin копируете контейнер состояния в свой, а при MouseButtonRelease очищаете его до следующего TouchBegin.

После того как на экране появляется второй «палец», генерация событий мышки отключается. И после этого, сколько бы вы пальцев ни ставили на экран или сколько бы ни оставляли, всегда генерируются события TouchUpdate. Когда все «пальцы» убираются с экрана, генерируется событие TouchEnd, а MouseButtonRelease нет. Проблем можно избежать, отреагировав на событие TouchEnd так же, как и на MouseButtonRelease. Но дело в том, что при следующей генерации TouchBegin события, MouseButtonPress не генерируется и вы будете дальше работать с событиями тачскрина. Вот тут-то и затаилась самая большая проблема.

MouseButtonPress не будет генерироваться до тех пор, пока не будет события MouseButtonRelease. Если MouseButtonRelease вызывать искусственно, то всё равно ничего не получится. Нужно поставить на экран и убрать только один «палец», после этого системно будет генерироваться MouseButtonRelease.
Эту проблему решал следующим образом. Вместе с TouchBegin искусственно вызывал событие MouseButtonPress. В функции обработке этого события вначале проверял состояние глобальной переменной, если она false, тогда ей присваивалось true и выполнялся код функции, если же она true значит, мы только что обрабатывали это событие, и просто выходим из функции. При TouchEnd или MouseButtonRelease этой переменной присваивался false.

Если бы в 5.4 ничего не поменялось в работе тачскрина, то этой части текста здесь могло бы и не быть. А так я очень остался недоволен. Раз в «пятилетку» баг выскакивает в работе тачскрина, но не могу его воспроизвести и как следствие — понять, почему он возникает. Как только это случится, то обязательно здесь отпишусь.


Что еще

Еще добавил перевод на английский, но там проблем не возникло, и инфы по интернационализации приложений в Qt достаточно.

Итоги

Игра была написана и успешно запущенна в проекте. Свои первоначальные предназначения она выполнила — мне набраться опыта в геймдеве и стать одним из заданий в городском квесте. Теперь она будет выполнять своё второстепенное предназначение — быть частью моего портфолио.

Спасибо Вам, за то, что Вы это читали.
Теги:
Хабы:
Всего голосов 30: ↑22 и ↓8+14
Комментарии14

Публикации

Истории

Работа

Программист C++
147 вакансий
QT разработчик
12 вакансий

Ближайшие события

19 августа – 20 октября
RuCode.Финал. Чемпионат по алгоритмическому программированию и ИИ
МоскваНижний НовгородЕкатеринбургСтавропольНовосибрискКалининградПермьВладивостокЧитаКраснорскТомскИжевскПетрозаводскКазаньКурскТюменьВолгоградУфаМурманскБишкекСочиУльяновскСаратовИркутскДолгопрудныйОнлайн
3 – 18 октября
Kokoc Hackathon 2024
Онлайн
24 – 25 октября
One Day Offer для AQA Engineer и Developers
Онлайн
25 октября
Конференция по росту продуктов EGC’24
МоскваОнлайн
7 – 8 ноября
Конференция byteoilgas_conf 2024
МоскваОнлайн
7 – 8 ноября
Конференция «Матемаркетинг»
МоскваОнлайн
15 – 16 ноября
IT-конференция Merge Skolkovo
Москва
25 – 26 апреля
IT-конференция Merge Tatarstan 2025
Казань