Мы решили поговорить с известной российской компанией HeroCraft, занимающейся играми, которая регулярно использует NDK в своей работе. Как этот инструмент помогает в разработке лучших игр и какие проблемы он решает – в этом интервью.
Почему возникла необходимость в использовании Native Development Kit?
Изначально код Race illegal: High Speed 3D был написан на C++ для платформы iOS/OS X. Поэтому мы хотели максимально упростить задачу портирования и поддержки игры в дальнейшем. Использование NDK позволило нам использовать примерно 90% кода без существенных изменений.
Как вы используете NDK в вашм приложении?
Вся логика игры, вызовы OpenGL команды для отрисовки графики, работа с файлами - все это написано на C++ и работает благодаря NDK. На языке Java реализована только оболочка, которая передает в NDK системные события, такие как обработка паузы, звонков, данные акселерометра и тачскрина.
Какие преимущества он дает?
Прежде всего это кроссплатформенность. По сути все, что происходит в игре - это логика и графика. Логику можно написать на С++, а графику выводить с помощью OpenGL. И именно NDK дает возможность использовать все это на Android. К тому же "тяжелые" куски кода со сложными вычислениями будут работать быстрее, чем аналогичные функции, написанные на Java. Например, в Race Illegal: High Speed 3D в мультиплеере используются хитрые алгоритмы для предсказания положения машины соперника, чтобы сгладить перебои с интернет соединением.
Еще одним плюсом является более гибкое управление памятью, правда с другой стороны приходиться быть более осторожным т.к. "уборщика мусора" тут нет. Так же NDK открывает доступ к использованию сторонних библиотек, написанных на C++, которые могут сильно облегчить разработку игрового проекта. В игре Race Illegal: High Speed 3D мы использовали модифицированные turbolibjpeg и libpng, которые на лету расшифровывали паки ресурсов и декодировали изображения.
Как вы ведете разработку с его помощью?
Саму оболочку на Java мы написали один раз и практически ее не меняли. Вся основная разработка игры ведется на С++ в Eclipse, где довольно неплохо реализована поддержка NDK, а отладка почти всегда позволяет выявить проблемные места. Управление подключением и настройкой сторонних библиотек через Android.mk может показаться сперва запутанным, но разобравшись, все оказывается довольно удобно и гибко.
Какую документацию вы используете?
Для работы с NDK пришлось, прежде всего, разобраться с документацией JNI, чтобы построить "мосты" между Java частью программы и C++. На практике оказалось, что даже сложные объекты или массивы можно легко перебрасывать из одной среды в другую, а для большинства мелких задач хватает всего пары универсальных функций. Например, в Race Illegal: High Speed 3D такой мост для работы с Google Play Services реализован всего через одну функцию и управляется передаваемыми параметрами.
Java Native Interface (JNI) — стандартный механизм для запуска кода, под управлением виртуальной машины Java (JVM), который написан на языках С/С++ или Ассемблера, и скомпонован в виде динамических библиотек, позволяет не использовать статическое связывание.
Какие инструменты вы еще с ним используете?
Для отладки игры мы часто используем эмулятор, однако скорость его работы "из коробки" оставляет желать лучшего. Но тут приходит на помощь Intel Hardware Accelerated Execution Manager, и эмулятор начинает работать в разы быстрее. Также мы используем статические анализаторы кода, например Infer от Facebook.
С какими трудностями вы столкнулись в разработке?
Основные трудности были при выявлении редких "крашей", которые возникали из-за неправильного управления памятью. В таких случаях далеко не всегда получается установить точное место падения и его причину. Например, программа может "потоптаться" по памяти и внешне это сразу никак не проявится, но как только вы обратитесь к испорченному куску памяти - будет краш. В Java с этим проще, по эксепшенам вы почти сразу понимаете, кто и почему стал причиной ошибки. Так же поддержка NDK в Android Studio реализована еще слабо, но с каждой версией ситуация улучшается.
Race illegal: High Speed 3D
Какие проблемы не решает NDK?
С помощью NDK нельзя работать напрямую с системными функциями девайса, в любом случае придется использовать хоть и минимальную, но оболочку на Java. Однако создать такую оболочку достаточно один раз и использовать во всех проектах. Все остальное NDK позволяет делать, к тому же оставляя место для кроссплатформенности. В случае с Race Illegal: High Speed 3D мы сэкономили много времени и сил на портировании именно благодаря NDK.
Спасибо, хороших вам игр!