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

от автора

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 проект и сел протестировать новый функционал, каково было моё удивление, когда обнаружил, что управление полетело. А произошло следующее.

Зачем то, разработчики Qt, поменяли логику работы событий тач скрина и мышки! Теперь это работает как то по чудному. При первом касании «пальца», генерируются события 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 достаточно.

Итоги

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

Игра лежит на Google Play, если кому интересно вот ссылка — https://play.google.com/store/apps/details?id=org.ppdevgroup.game. Там еще одна игра лежит, тоже на Qt мною написана.

Спасибо Вам, за то, что Вы это читали.

ссылка на оригинал статьи http://habrahabr.ru/post/256879/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *