Написание игры под Android на C++ с помощью MoSync
Примерно в декабре 2012 появилось острое желание спрограммировать самому игрушку для Андроида. Чтобы хоть она не падала, и не была медленной и (сильно) убогой.Дня два я просматривал табличку с возможными вариантами средств разработки. Требования — бесплатность, Андроид и Си-плюс-плюс. Я выбрал MoSync.
Результат: год работы над проектом, уход с работы и файл .apk на GooglePlay размером 1,7 Мб.
А теперь для желающих — подробно: В 2011-ом у меня был миниатюрный опыт разработки для мобильных устройств на JavaScript-e.… Ну как разработки… точнее — реанимации сдохшего и заброшенного проекта. Я считаю, опыт крайне неудачный, он надолго отбил интерес. А вначале был культурный шок от осознания: то есть я буду писать убогие игры, крайне далёкие от Starcraft-a (и похожих), для людей, которые согласны заплатить две моих зарплаты за девайс, на котором можно будет играть только вот в такое убожество…
В декабре 2012 ситуация немного изменилась: в нашем «районном универсаме» появились дешёвые планшеты; я посмотрел количество скачивания популярных игр на GooglePlay, плюс у меня началась ломка от трёх месяцев без программирования — и я решился.
Первые шаги прошли легко: скачать и поставить студию MoSync, скомпилить программку-пример, порадоваться, что удалось запустить её в эмуляторе.Ещё через какае-то время удалось запустить её на планшете.Дальше был первый большой шок: дебаг программы в эмуляторе — он работал не всегда, и крайне не предсказуемо… Значения для переменных показывались не всегда правильные, формулы не поддерживались, содержание сложных структур вообще не показывалось, и вообще программа иногда ломалась — не из-за кода, как выяснилось после бессонных ночей.Спасал только вывод информации на консоль.
Во-первых мне хотелось пальцами погонять картинки по экрану — то есть познакомиться с главным достоинством планшетов — самым удобным интерфейсом — тачскринистым. Выяснилось, что функций для вывода графики немного (функция круг/окружность вообще «самопальная») и что картинки (битмапы) я выводить (пока) не умею. Но самое главное — если вести пальцем по экрану планшета — была задержка, и похоже это проблема Андроида или тач-экранов.
А дальше началось «сделай сам».Мне пришлось (и я это сделал) создать несколько Engine-ов. То есть, если я хотел добавить в проект какую-то «фичу» (особенность), мне нужно было знакомится с ней, изучать как её спрограммить и вставить правильно, и какие у неё возможности. Дальше с этими «фичами» мне было удобнее работать через Engine, при необходимости я изменял его… (без наследования, каюсь)
Во-первых был создан «Screen-Engine» — меня категорически не устраивало делать программу под какой-то конкретный размер экрана — я хотел работать с виртуальным экраном, а как его вывести на реальный — проблема Screen-Engine-а. Так же он конвертировал касание пользователя к экрану в виртуальные координаты, делал scroll (прокрутку виртуального экрана по меньшему реальному), pinch-zoom-in и pinch-zoom-out (изменение масштаба двумя пальцами). Это заняло больше всего времени — примерно месяца 3–6 — включая такие примочки, как замирание если аппликация не активна (чтоб не жрать батарейку и процессорное время зря) и показ пользователю определённых мест — «вот, это карта, отсюда ты начинаешь, а враг — примерно там».
Далее поляки выпустили FreeCiv (бесплатная версия Цивилизации) под Android, и я проверил, будет ли у меня так же всё тормозить, если я буду отрисовывать карту «стратегии» из тайлов… Результат мне понравился, я решил обязательно вернуться к этой теме, но позже.Затем (это был апрель-май, год назад) я решил выпустить игру попроще, ибо запутался в формалах тригонометрии и кинематики… Поскольку близкие во всю играли в Филлер, я решил делать его — будут проверять-тестить. Дабы не выпускать «ещё один HelloWorld», нужно было придумать, чем моя игра будет выделятся. Я решил, что раз это на Си —, а значит работать будет быстрей, чем Ява — то это будет не фиксированный размер экрана, поле — больше, чем у «конкурентов», какая-то анимация, и более «умный» ИИ.Плюс я почувствовал, что нужна более простая игра, чтобы создать и протестить, «обкатать» все будущие Engine-ы — было похоже, что их понадобится немало.
Вторым Engine-ом стал Multi-Language-Engine. Он смотрел локаль (страна-язык мобильного устройства), загружал нужный язык (если не было — тогда дефолтный) и делал конвертации: UTF-8 (Multi-Byte-String) в Unicode и обратно — дело в том, что на экран игры (где отрисовка графики) нужно было выводить в Юникоде, а в менюшки — в UTF-8.Так же Multi-Language-Engine формировал сообщения с параметрами — типа «у вас xxx дерева, yyy камня и zzz золота», для английского — «You have xxx wood, yyy stone and zzz of gold», и так — для всех поддерживаемых языков.В начале выяснилось (после нескольких бессонных ночей), что Кхмерский язык не поддерживается — у шрифтов эмулятора и девайса нету букв для этого языка — ни в Юникоде, ни в UTF-8.В конце выяснилось, что язык Хинди (а их 600–700 миллионов человек) не загружается корректно в UTF-8 (там более 4 байт на символ), но всё хорошо, если загружать его в Юникоде.
Дальше была работа с менюшками и диалогами — выяснилось (после долгих бессонных), что в MoCync элементы диалогов нужно не стирать, как в Си++, не обнулять, как в Яве, а оставлять нетронутыми — только тогда система их корректно сама… утилизирует.Мне не понравилось, что у чек-бокса нажимается только кнопка, а не плюс ещё вся фраза, как в Виндах — пришлось писать своё…Я не нашёл нормального элемента для набора числа — пришлось не только делать «своё», но ещё и добиваться, чтоб он был определённой ширины; какой — не знаю, узнаю кода он будет показан — от шрифта зависит…Последними элементами по желанию были «рамочка вокруг чего-скажут» и горизонтальная линия (в принципе, та же рамочка, но на всю ширину).После всех этих нововведений диалоги и менюшки перестали корректно уничтожаться, но эти было не критично — тихо висели в памяти.
AudioEngine — пляски с бубном продолжаются. Потому, что выяснилось, что не все функции корректно работают. Разработчики MoSync перестали отвечать и фиксить, потому что MoSync обанкротился. Но поскольку сил и времени уже было вложено много, то… Результат: громкость каждого звука не регулируется, но зато их можно не только останавливать и проигрывать, но даже ставить на паузу — это нужно, если аппликация не активна. Добиться этого удалось склеив стабильную версию библиотек студии »3.3.1» и «ночного билда с фиксом». Правда при этом аппликация перестала билдиться в Debug (отладочном) режиме. Но… он слегка полезен только запуская аппликацию в эмуляторе, а звуки и менюшки-диалоги в эмуляторе не работают — только на реальном девайсе.Причина создания AudioEngine — автоматическая загрузка звуковых ресурсов, их более удобное проигрывание (и прочие функции), автоматические пауза (если аппликация не активна) и resume (возобновление проигрышей звуков), автоматическая работа с памятью — освобождение памяти звуков, что больше не используются; возможность проигрыша одного и того же звука одновременно более одного раза.
«Ёжики кололись и плакали, но продолжали…»
Я решил добавить не просто стены, а лабиринт — спасибо пользователю aivanov за публикацию его генератора лабиринтов aivanov.com/maze-generator/ — я его использовал.Затем, чтобы играть стало ещё интересней, я добавил «fog of war» (туман войны), чтобы… интриговать пользователя «а туда ли я иду» в случае лабиринта, и «а далеко ли идут эти слепленные ячейки одного цвета» при выборе цвета.После этого пришлось переделывать анимацию, дабы неизведанные ячейки «открывались» красиво; отдельно пришлось поработать с рамками вокруг ячеек; к сожалению, этого стало почти не заметно после того, как были сделаны картинки=битмапы на ячейки.Дальше — не так интересно: составление, сохранение-загрузка и отрисовка Таблицы лучших результатов, и картинки=битмапы на ячейки.Вначале я их сделал такими, как хотел год назад — задумывая этот проект:
1: Большая страшная картинка Результат (после года работы) мне не понравился, конечный вид:
2: Большая картинка с белыми боками 3: Большая картинка без белых боков Я использовал один тайл 200×200 пикселей, при старте программы делались его копии меньших размеров. Если этот тайл нужен большего размера — он увеличивается программно прямо во время отрисовки — имхо тормозит не сильно. Но тогда время старта программы увеличилось до катастрофических 7+ секунд. Плюс тайлы выглядели не красиво при зуме. Пришлось ресайзить их вручную, со всеми экспериментами это заняло пару дней, зам ресайз — 2–4 часа. Время старта программы уменьшилось до нормального — 2–3 секунды.
Один из последних штрихов — использование не стандартных, а «красивых» цветов. Для этого я почувствовал (типографским прошлым), что нужно использовать не RGB, а HSL цветовую модель… тогда насыщенность и светлота остаются примерно одинаковыми, а тоны цветов ячеек выбираются, деля 360 градусов на количество цветов на карте.
Последние изменения — отдав другу тестировать новоиспечённую игруху, состоялся разговор как по «испорченному телефону»: — Меню нажми. — Где? — Ну кнопку «меню». — Где она у тебя? — Она у тебя на девайсе! … выяснилось, что не все девайсы имеют кнопку «меню» на корпусе. Пришлось добавить на экран кнопки «Menu» и на всякий случай — «Back».
Следующее — релиз на Google Play. Кратко, новое для меня: мне было интересно, как быстро мая аппликация станет заметна — без раскрутки. Просто задавая поиск по её названию. Результаты: почти моментально игра находилась по редкой фразе «MoSync». Через неделю — по «Flood Filler». По «Color Flood Filler» (её название) — только через две недели после её появления на Google Play. Так же по этой фразе (на чужом компе) неожиданно выскакивали скриншоты из игры с пометкой «добавлено 3 дня назад».
Скриншоты для описания игры на Google Play: требуются для «телефона», 7-дюймового планшета и для 10-дюймового планшета. Нашёл, что принимаются размеры: 320×480, 480×800, 480×854,1280×720 и 1280×800.Я «вкинул» скриншот 320×480 в секцию для «телефона», 480×800 — для 7-дюймового планшета и 1280×800 для 10-дюймового планшета. Результат мне не понравился: и на телефоне (с экраном 320×480) и на планшете (с экраном 480×800) я вижу все скриншоты, из всех трёх групп. Вопрос: что я делаю не так?
Следующие задачи — перевод игры на заявленные 42 языка (с помощью гугль-переводчика, если на translatewiki.net проект не пустят; кстати, файл для одного языка занимает примерно 4000 символов); и, видимо ещё важнее — перевести описание игры для Google Play.После этого, в конце, планирую вставить инфу, как отблагодарить автора финансово (номера счетов кредиток) — правда подозреваю, что гипотетический донат не окупит не только год работы, но даже хотя бы то время, что я буду эту инфу вставлять.
Так же хорошо бы улучшить геймплей и интересность игры: к сожалению, игра стала довольно сложной, дальше пятого уровня пройти не получается. Даже несмотря на то, что в таких случаях игра меняет очерёдность хода для игрока-человека.
Адрес игры на Google Play: play.google.com/store/apps/details? id=com.mosync.app_FloodFillerЛюбые предложения и конструктивная критика — принимаются. А за помощь буду вообще благодарен! :)