Привет хабрасообщество!
Тема написания приложений под андроид на С++ незаслуженно забыта. Сегодня мы узнаем как писать многоплатформенные приложения под Android используя Linderdaum Engine.
Пост обновлён, чтобы поддержать совместимость с Linderdaum SDK 0.6.08
1. Настройка билдпроцесса
Чтобы работать с Linderdaum Engine сначала придётся установить:
Кроме того, для сборки непосредственно под Android дополнительно понадобятся установленные:
Устанавливаем всё вышеперечисленное. Linderdaum SDK устанавливаем в папку, в имени которой нет пробелов (иначе будут проблемы с Android NDK). В Linderdaum SDK есть все нужные для сборки библиотеки в скомпилированном виде (лежат в Libs.Win32/Libs.Win64 и BuildAndroid/jni/armeabi-v7a), поэтому достаточно только обновить метаинформацию и билдфайлы. Запускаем из каталока с SDK сначала rebuildLSD.py, а затем makeconfig.py. Всё — теперь можно начинать писать наше первое многоплатформенное приложение.
2. Наше HelloAndroid приложение
Чтобы не загружаться деталями движка, а более подробно остановиться на многоплатформенности, рассмотрим вот такое минималистическое 3D приложение, которое мы положим в файл Apps/Test_Android/Src/Test_Android.cpp:
Как не трудно понять, этот код должен вывести красный икосаэдр в центре экрана с возможность вращать его мышью. И, как мы хотим, должен это делать без изменений на андроидном девайсе и на PC под Windows. Сказано — сделано.
3. Сборка под Windows
Воспользуемся билдсистемой Linderdaum'а и автосгенерим все билд файлы. Создаём пустые файлы Apps/Test_Android/makeconfig.py и Apps/Test_Android/jni/Android.mk — они будут автосгенерены (второй нам потребуется чуть позже, поэтому заодно создадим и его). Переходим в корень движка и оттуда запускаем Solution/regenerateconfigs.py. Потом запускаем makeconfig.py. Вуаля — файлы .vcproj/.vcxproj для студии и мэйкфайл для gcc готовы.
Загружаем LinderdaumSDK_VS2008.sln (либо LinderdaumSDK_VS2010.sln) и добавляем к солюшено проект Apps/Test_Android, не забыв выставить ему Dependency на Linderdaum Engine.
Нажимаем F5 — появляется окно с красным икосаэдром (см. скриншот внизу страницы).
P.S. Тем кто хочет использовать gcc под Windows достаточно после генерации мейкфайлов запустить build.py и немного подождать.
4. Сборка движка под Android
Теперь, когда путь Windows освоен, мы готовы приступить к сборке приложения под Андроид. Это очень легко, но потребует настройки наших тулзов:
Нужно собрать движок под андроид (в комплекте с SDK уже идёт libLinderdaumEngineCore.a, поэтому ручная пересборка нужна только если вы хотите самостоятельно поковыряться в движке). Запускаем Cygwin Bash Shell, переходим в папку BuildAndroid и говорим ndk-build -j4. Немного ждём… В результате должен появиться libLinderdaumEngineCore.a размером чуть больше 100 Мб.
5. Сборка проекта под Android
Для сборки нашего минипроекта под Android подребуется ещё несколько файлов в Apps/Test_Android. Вот что в них нужно написать:
ant.properties
project.properties
local.properties
res\values\strings.xml
jni\Application.mk
Для использования тулзов из Android SDK нам потребуется манифест AndroidManifest.xml. Например, вот такой:
В будущем не забываем менять строку package=«com.linderdaum.engine.myfirstandroidapp» в разных приложениях.
После того, как мы перейдём в Apps\Test_Android и запустим ndk-build из Сygwin'a, должно появиться следующее:
Мы закончали с C++ частью нашего проекта. Осталось добить Java и собрать дистрибутив в .apk. Для этого нам потребуется вот такой build.xml:
Запускаем ant copy-common-media debug и получаем готовый дистрибутив в Apps\Test_Android\bin\Test_Android-debug.apk. Его можно установить на девайс командой:
adb install Test_Android-debug.apk
и запустить приложение. Должно появиться вот такое:

Сразу отвечаю на некоторые предполагаемые вопросы:
1. Есть ли возможность создавать приложения под Windows, именно под настольную версию? MacOS?
Можно создавать приложения под Windows XP/Vista/7, как под 32-х так и под 64-битные версии. Причём приложение не потребует никаких изменений игрового кода при сборке под Android, всё будет работать — и графика, и звук, и всё остальное. Версии движка под MacOS пока нет.
2. Есть/будет/когда поддержка WP7?
На данный момент нет. О поддержке WP7 можно будет говорить после релиза C++ API для данный платформы от Microsoft'a.
3. Какая ситуация с Android 2.1/2.2/2.3/3.0 со стороны движка? Различия?
С++ и Java части движка поддерживают Андроиды начиная от 2.1 и старше. Различия могут быть, если вы захотите писать Java код для игры, который не будет работать с 2.1/2.2.
4. Для реализации движка на Android используется NDK или код движка написан на Java?
Движок написан на С++ c обёрткой на Java и использует Android NDK для сборки. С++ код работает под все поддерживаемые платформы.
5. Насколько хороши «обёртки» над устройствами ввода, мультитач, мгновенный/буферизированный ввод?
Поддерживается мультитач. Буферизацию и распознавание жестов придётся делать самому.
6. Для 2D/3D используется только fixed-function или есть возможность использовать шейдеры?
Движок основан на OpenGL 3 / OpenGL ES 2 и использует только шейдеры. Fixed-function использовать невозможно.
7. Какие приложения уже написаны на движке?
market.android.com/details?id=com.linderdaum.engine.puzzL
market.android.com/details?id=com.linderdaum.engine.multibricks_free
8. Почему так много букв, чтобы создать приложение?
В академических целях. Всё вышеперечисленное можно сделать в 5 кликов используя ProjectWizard из Linderdaum SDK.
Дополнение
Чтобы быстро сделать Android-приложение ещё быстрее, запускаем Project Wizard, там выбираем:
Другие опции оставляем по-умолчанию и жмём Generate Project. Всё! Не забываем в local.properties прописать путь к своему Android SDK.
Тема написания приложений под андроид на С++ незаслуженно забыта. Сегодня мы узнаем как писать многоплатформенные приложения под Android используя Linderdaum Engine.
Пост обновлён, чтобы поддержать совместимость с Linderdaum SDK 0.6.08
1. Настройка билдпроцесса
Чтобы работать с Linderdaum Engine сначала придётся установить:
- Linderdaum Engine SDK 0.6.08;
- OpenAL;
- Python 3 (обязательно версии 3 или старше).
Кроме того, для сборки непосредственно под Android дополнительно понадобятся установленные:
- Android SDK r16;
- Android NDK r7;
- Cygwin (мы говорим про сборку под Windows);
- Apache Ant;
- Java SE Development Kit;
- ещё девайс, желательно с Андроид 2.2 и выше, но если совсем туго, то подойдёт и с 2.1.
Устанавливаем всё вышеперечисленное. Linderdaum SDK устанавливаем в папку, в имени которой нет пробелов (иначе будут проблемы с Android NDK). В Linderdaum SDK есть все нужные для сборки библиотеки в скомпилированном виде (лежат в Libs.Win32/Libs.Win64 и BuildAndroid/jni/armeabi-v7a), поэтому достаточно только обновить метаинформацию и билдфайлы. Запускаем из каталока с SDK сначала rebuildLSD.py, а затем makeconfig.py. Всё — теперь можно начинать писать наше первое многоплатформенное приложение.
2. Наше HelloAndroid приложение
Чтобы не загружаться деталями движка, а более подробно остановиться на многоплатформенности, рассмотрим вот такое минималистическое 3D приложение, которое мы положим в файл Apps/Test_Android/Src/Test_Android.cpp:
#include "Linderdaum.h" sEnvironment* Env = NULL; LMatrix4 Projection; clVirtualTrackball Trackball; clGameCamera* Camera = NULL; clScene* Scene = NULL; void DrawOverlay(LEvent Event, const LEventArgs& Args) { // обновим камеру LMatrix4 Trans( Trackball.GetRotationMatrix() * Camera->GetCamera().GetModelViewMatrix() ); Scene->SetCameraTransform( Trans ); Scene->SetCameraProjection( Projection ); // отрисуем сцену Scene->SetUseOffscreenBuffer( false, false ); Scene->RenderForward(); // обновим виртуальный трэкбол bool MousePressedL = Env->Console->IsKeyPressed( LK_LBUTTON ); Env->Viewport->UpdateTrackball( &Trackball, 10.0f, MousePressedL ); } void Update( LEvent Event, const LEventArgs& Args ) { // в Args.FFloatArg хранится DeltaTime в миллисекундах } APPLICATION_ENTRY_POINT { LString CommandLine; EXTRACT_COMMAND_LINE(CommandLine); Env = new sEnvironment(); // CommonMedia используется только на PC, на Андроиде она будет хитро упакована в ресурсы Env->DeployDefaultEnvironment( CommandLine, "..\\..\\CommonMedia" ); Env->FileSystem->Mount("GameData"); Projection = Math::Perspective( 45.0f, Env->Viewport->GetAspectRatio(), 0.4f, 2000.0f ); // создадим камеру и подпишем её на события Camera = Env->Linker->Instantiate( "clGameCamera" ); Camera->GetCamera().SetPosition( LVector3(0,-10,10) ); CONNECTOBJ( L_EVENT_TIMER, &clGameCamera::Event_TIMER, Camera ); Env->Connect( L_EVENT_DRAWOVERLAY, Utils::Bind( &DrawOverlay ) ); Env->Connect( L_EVENT_TIMER, Utils::Bind( &Update ) ); // создадим сцену Scene = Env->Linker->Instantiate("clScene"); // и добавим в неё меш int ID = Scene->AddGeom( Env->Resources->CreateIcosahedron( 3.0f, LVector3(0) ) ); // установим ему материал clMaterial* Mtl = Env->Resources->CreateMaterial(); Mtl->SetPropertyValue( "DiffuseColor", "1.0 0.0 0.0 0" ); Mtl->SetPropertyValue( "CastShadow", "false" ); Scene->SetMtl( ID, Mtl ); // установим положение Scene->SetLocalTransform( ID, LMatrix4::GetTranslateMatrix( LVector3( 0.0f, 0.0f, 0.0f ) ) ); Env->RunApplication( DEFAULT_CONSOLE_AUTOEXEC ); APPLICATION_EXIT_POINT( Env ); } APPLICATION_SHUTDOWN { }
Как не трудно понять, этот код должен вывести красный икосаэдр в центре экрана с возможность вращать его мышью. И, как мы хотим, должен это делать без изменений на андроидном девайсе и на PC под Windows. Сказано — сделано.
3. Сборка под Windows
Воспользуемся билдсистемой Linderdaum'а и автосгенерим все билд файлы. Создаём пустые файлы Apps/Test_Android/makeconfig.py и Apps/Test_Android/jni/Android.mk — они будут автосгенерены (второй нам потребуется чуть позже, поэтому заодно создадим и его). Переходим в корень движка и оттуда запускаем Solution/regenerateconfigs.py. Потом запускаем makeconfig.py. Вуаля — файлы .vcproj/.vcxproj для студии и мэйкфайл для gcc готовы.
Загружаем LinderdaumSDK_VS2008.sln (либо LinderdaumSDK_VS2010.sln) и добавляем к солюшено проект Apps/Test_Android, не забыв выставить ему Dependency на Linderdaum Engine.
Нажимаем F5 — появляется окно с красным икосаэдром (см. скриншот внизу страницы).
P.S. Тем кто хочет использовать gcc под Windows достаточно после генерации мейкфайлов запустить build.py и немного подождать.
4. Сборка движка под Android
Теперь, когда путь Windows освоен, мы готовы приступить к сборке приложения под Андроид. Это очень легко, но потребует настройки наших тулзов:
- переменная окружения JAVA_HOME должна ссылаться на папку с JDK (на Ubuntu с OpenJDK это обычно /usr/lib/kvm/default-java);
- переменная окружения NDK_ROOT должна ссылаться на папку с Android NDK;
- в файле Apps/Test_Android/local.properties нужно указать, чтобы параметр 'sdk.dir=' указывал на папку с Android SDK.
Нужно собрать движок под андроид (в комплекте с SDK уже идёт libLinderdaumEngineCore.a, поэтому ручная пересборка нужна только если вы хотите самостоятельно поковыряться в движке). Запускаем Cygwin Bash Shell, переходим в папку BuildAndroid и говорим ndk-build -j4. Немного ждём… В результате должен появиться libLinderdaumEngineCore.a размером чуть больше 100 Мб.
5. Сборка проекта под Android
Для сборки нашего минипроекта под Android подребуется ещё несколько файлов в Apps/Test_Android. Вот что в них нужно написать:
ant.properties
android.library.reference.1=..\\\\..\\\\BuildAndroid
project.properties
target=android-13
local.properties
sdk.dir=<здесь путь к вашему Android SDK, например D:\\android-sdk-windows>
res\values\strings.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">Test_Android</string> </resources>
jni\Application.mk
APP_OPTIM := release
APP_PLATFORM := android-7
APP_STL := gnustl_static
APP_CPPFLAGS += -frtti
APP_CPPFLAGS += -fexceptions
APP_CPPFLAGS += -DANDROID
APP_ABI := armeabi-v7a
Для использования тулзов из Android SDK нам потребуется манифест AndroidManifest.xml. Например, вот такой:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.linderdaum.engine.myfirstandroidapp" android:versionCode="1" android:versionName="0.6.00" android:installLocation="auto"> <!--require Android 2.1 and higher--> <uses-sdk android:minSdkVersion="7" /> <uses-sdk android:targetSdkVersion="9" /> <supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:anyDensity="true" /> <uses-feature android:glEsVersion="0x00020000"/> <uses-feature android:name="android.hardware.telephony" android:required="false" /> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <application android:label="@string/app_name" android:installLocation="preferExternal" android:debuggable="false"> <activity android:name="com.linderdaum.engine.LinderdaumEngineActivity" android:launchMode="singleTask" android:theme="@android:style/Theme.NoTitleBar.Fullscreen" android:screenOrientation="landscape" android:configChanges="orientation|keyboardHidden" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
В будущем не забываем менять строку package=«com.linderdaum.engine.myfirstandroidapp» в разных приложениях.
После того, как мы перейдём в Apps\Test_Android и запустим ndk-build из Сygwin'a, должно появиться следующее:
$ ndk-build Compile++ thumb : LinderdaumEngine <= LAndroid.cpp Compile thumb : LinderdaumEngine <= LJNI.c Compile++ thumb : LinderdaumEngine <= Test_Android.cpp Prebuilt : libLinderdaumEngineCore.a <= jni/../../../BuildAndroid/obj/local/armeabi-v7a/ Prebuilt : libFreeImage.a <= jni/../../../BuildAndroid/jni/armeabi-v7a/ Prebuilt : libFreeType.a <= jni/../../../BuildAndroid/jni/armeabi-v7a/ Prebuilt : libVorbis.a <= jni/../../../BuildAndroid/jni/armeabi-v7a/ Prebuilt : libOGG.a <= jni/../../../BuildAndroid/jni/armeabi-v7a/ Prebuilt : libOpenAL.a <= jni/../../../BuildAndroid/jni/armeabi-v7a/ Prebuilt : libModPlug.a <= jni/../../../BuildAndroid/jni/armeabi-v7a/ Prebuilt : libstdc++.a <= <NDK>/sources/cxx-stl/gnu-libstdc++/libs/armeabi-v7a/ SharedLibrary : libLinderdaumEngine.so Install : libLinderdaumEngine.so => libs/armeabi-v7a/libLinderdaumEngine.so
Мы закончали с C++ частью нашего проекта. Осталось добить Java и собрать дистрибутив в .apk. Для этого нам потребуется вот такой build.xml:
<?xml version="1.0" encoding="UTF-8"?> <project name="Asteroids" default="help"> <import file="../../BuildAndroid/CommonMedia.xml"/> <property file="local.properties" /> <property file="ant.properties" /> <loadproperties srcFile="project.properties" /> <fail message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through an env var" unless="sdk.dir" /> <target name="copy-game-data"> <!-- Game data --> <delete dir="assets"/> <copy todir="assets/Data"> <fileset dir="GameData"> </fileset> </copy> <copy todir="assets/Data"> <fileset dir="Data"> </fileset> </copy> </target> <import file="${sdk.dir}/tools/ant/build.xml" /> </project>
Запускаем ant copy-common-media debug и получаем готовый дистрибутив в Apps\Test_Android\bin\Test_Android-debug.apk. Его можно установить на девайс командой:
adb install Test_Android-debug.apk
и запустить приложение. Должно появиться вот такое:

Сразу отвечаю на некоторые предполагаемые вопросы:
1. Есть ли возможность создавать приложения под Windows, именно под настольную версию? MacOS?
Можно создавать приложения под Windows XP/Vista/7, как под 32-х так и под 64-битные версии. Причём приложение не потребует никаких изменений игрового кода при сборке под Android, всё будет работать — и графика, и звук, и всё остальное. Версии движка под MacOS пока нет.
2. Есть/будет/когда поддержка WP7?
На данный момент нет. О поддержке WP7 можно будет говорить после релиза C++ API для данный платформы от Microsoft'a.
3. Какая ситуация с Android 2.1/2.2/2.3/3.0 со стороны движка? Различия?
С++ и Java части движка поддерживают Андроиды начиная от 2.1 и старше. Различия могут быть, если вы захотите писать Java код для игры, который не будет работать с 2.1/2.2.
4. Для реализации движка на Android используется NDK или код движка написан на Java?
Движок написан на С++ c обёрткой на Java и использует Android NDK для сборки. С++ код работает под все поддерживаемые платформы.
5. Насколько хороши «обёртки» над устройствами ввода, мультитач, мгновенный/буферизированный ввод?
Поддерживается мультитач. Буферизацию и распознавание жестов придётся делать самому.
6. Для 2D/3D используется только fixed-function или есть возможность использовать шейдеры?
Движок основан на OpenGL 3 / OpenGL ES 2 и использует только шейдеры. Fixed-function использовать невозможно.
7. Какие приложения уже написаны на движке?
market.android.com/details?id=com.linderdaum.engine.puzzL
market.android.com/details?id=com.linderdaum.engine.multibricks_free
8. Почему так много букв, чтобы создать приложение?
В академических целях. Всё вышеперечисленное можно сделать в 5 кликов используя ProjectWizard из Linderdaum SDK.
Дополнение
Чтобы быстро сделать Android-приложение ещё быстрее, запускаем Project Wizard, там выбираем:
- C++ empty project;
- Project Folder ставим в подкаталог установленного движка (иначе не будет работать Android NDK);
- нажимаем Next...;
- отмечаем «Generate Android SDK and NDK configs» и «Add events processing code: Events + Scene»;
- ставим Resolution: 800x480 (это нужно для PC, на девайсе будет использоваться полное разрешение экрана).
Другие опции оставляем по-умолчанию и жмём Generate Project. Всё! Не забываем в local.properties прописать путь к своему Android SDK.
