Дорогие друзья, сегодня я расскажу вам о фреймворке высокого уровня на Lua для мобильных платформ собственной разработки. Как вы уже, наверное, догадались из названия, этот фреймворк использует другой низкоуровней фреймворк для отрисовки графики и для взаимодействия с системой. В качество него выступает MOAI. Для минимального ознакомления с ним, я рекомендую прочитать мою предыдущую статью habrahabr.ru/post/176765/
Прежде всего, какие задачи должен был решить новый фремворк?
Во-первых, проблемы с фрагментацией экранов. А во-вторых (та-дам), хотелось иметь какой-то, пусть и простейший, графический редактор интерфейсов. В третьих, фреймворк должен был определить архитектуру и файловую структуру приложения в целом. Хочу сказать, что кода получилось немного (менее 600 строк), поэтому, даже если фреймворк вам не подойдет, как есть, будет несложно разобраться с его работай и заточить его под свои нужды.
Warning: фреймворк заточен под landscape приложения, поэтому если вам нужен портретный режим, то скорее всего придется потратить некоторое время на доработку.
Вернемся к фрагментации экранов.
Чтобы решить проблему фрагментации, нужно, чтобы приложение учитывало:
- Разные размеры экранов
- Разные разрешения
- Разные пропорции
Для того, чтобы решить все эти три задачи одним махом, Corona SDK или Gideros предлагают выбрать policy масштабирования всего приложения. Наиболее адекватный из этих режимов — так называемый letterbox. Это когда приложение равномерно масштабируется до размеров экрана, но при этом остаются черные полосы по краям в случае несовпадения пропорций.
В MOAI как такового режима нет, но есть снипетс, как реализовать это в несколько строк, манипулируя параметрами viewport.
Понятно, что такая полумера не может удовлетворить по-настоящему хорошее приложение. Экраны мобильных устройств и без того малы, чтобы еще их площадь съедалась черными полосами.
Очевидно, что не обойтись без эластичной верстки (решаем проблему размеров/пропорций).
Что касается разных разрешений экрана, то это легко решается набором разной графики или же ее масштабированием. Однако, в Android/iOS эти механизмы работают по-разному, поэтому придется реализовывать его самим.
Спрайтовый графический редактор
Графический редактор был написан при помощи PyQt. Он довольно прост и умеет манипулировать только спрайтами, то бишь картинками.
MOAI поддерживает отображение текста, но ни графический редактор, ни Terevaka не могут его показывать. На практике это означает, что если поверх кнопки нужно нанести текст, то это нужно сделать програмно после загрузки спрайта кнопки (либо нанести текст прямо на спрайт кнопки, лол).
Тем не менее, графический редактор — это мощный инструмент, т. к. позволяет не только разместить элементы графически, но и отделить вид от логики программы.
Графический редактор хранит файл проекта в JSON файле и экспортирует слой во внутреннее представление Terevaka (Lua файл) по принципу один файл — один слой.
Слои бывают двух типов- elastic и scalable.
Elastic слой при отображении размещает элементы в зависимости от сторон привязки. Т.е. если вы хотите, чтобы элемент при масштабировании следовал правому верхнему углу, то нужно указывать координаты относительно этого угла.
Пример, слой в редакторе:
Iphone 3.5 Inch:
Iphone 4 inch:
Ipad:
Scalable слой — это другой тип слоя, который масштабируется пропорционально, наподобие letterbox. К примеру, главное меню имеет смысл делать именно при помощи scalable слоя, но фон, однако, лучше сделать на весь экран.
Пример, слой в редакторе:
Iphone 3.5 Inch:
Iphone 4 Inch:
Ipad:
В редакторе, пропорции scalable слоя указаны фиксировано 427x320. Это пропорции айпада, уменьшенные до размера iphone. Вы можете выбрать более удобные для себя параметры, однако нужно помнить о разрешении графики, которая будет использоваться в дизайнере и непосредственно в приложении. Для себя я использую 853х640 (изменять параметр нужно прямо в исходниках графического редактора) и заливаю в редакторе retina графику. В самом приложении, как правило, использую текстуры еще более высокого разрешения, чтобы графика соотвествовала большим ретина экранам, а во время загрузки слоя указываю параметр dpiMultiplier, чтобы спрайты загрузились нужного размера.
Причина по которой я захардкодил 427х320 попорции — с размерами/разрешениями легко запутаться, поэтому кто понимает что к чему, разберется, как адаптировать это под свой случай.
Так, комбинируя подходы, можно довольно быстро создавать гибкую графику.
Файлы со слоями хранятся в директории ./res/layout/ по аналогии с Android.
Фрагментация разрешений экранов
Разные разрешения экрана поддерживаются двойным набором графики.
Набор графики с обычным разрешением хранится в ./res/drawable-mdpi/, а ретина — в ./res/drawable-xhdpi/. Если разрешение экрана не совпадает с одним из этих, то будет взят наиболее подходящий набор и смасштабирован. Директории ./res/drawable-ldpi и ./res/drawable-hdpi пока не поддерживаются движком.
Важный момент — при загрузке слоя желательно использовать упакованные спрайты в одну текстуру для того, чтобы оптимизировать объем расходуемой памяти. В фрейворке поддерживается MOAI формат, в который умеет конвертировать платный TexturePacker.
Warning: не используйте в TexturePacker упаковку текстур с удалением пустых областей, т. к. в экспортере в формат MOAI есть баг и графика в итоге поплывет.
Разное
Для получения спрайта из слоя используйте функцию findPropById (опять-таки аналогия с Android)
Для обработки нажатия на спрайт, достаточно приаттачить специальный callback (см. пример в terevaka-samples).
Другие различные примеры использования смотрите в проекте terevaka-samples. Чтобы запустить пример, скопируйте tereavaka в папку примера, а еще лучше — сделайте в нее симлинк.
Чтобы протестировать приложение под разными экранами, вовсе не нужно много разных устройств — используйте профили запуска. Готовые профили лежат в каталоге ./terevaka/profiles.
Для запуска с профилем, используйте команду moai ./terevaka/profiles/ipad.lua main.lua, где ipad.lua — профиль айпада. В профиле как правило 3-4 строки, вы можете с легкостью создать свои профили.
Спрайты для ui builder нужно сохранять в разрешении mdpi.
Резюме
Изначально проект начинался, как выделение некого общего кода из кода моей новой игры. В попытке структурировать, как сам код, так и требования к нему, привели к появлению фреймворка, а затем, используя мои старые наработки, и графического дизайнера к нему. Помимо этого, пришлось дорабатывать и сам MOAI, однако благодаря быстрому отклику его разработчиков, все изменения уже внесены в основной репозиторий.
Также — это показательный опыт, что не нужно боятся писать свои библиотеки, если четко понимаете требования к ним, а также если пишете на скриптовом языке :)
Ссылки
Terevaka: github.com/Nepherhotep/terevaka
Samples: github.com/Nepherhotep/terevaka-samples
UI Builder: github.com/Nepherhotep/terevaka-ui-builder
Official MOAI: github.com/moai/moai-dev
My fork: github.com/Nepherhotep/moai-dev
Автор: Nepherhotep