Привет хабрасообщество!
Тема написания приложений под андроид на С++ незаслуженно забыта. Сегодня мы узнаем как писать многоплатформенные приложения под 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.