[Из песочницы] Кроссплатформенное приложение в Android Studio на jMonkeyEngine 3

418a4b94d1764fb0b5a75a0ffff181d6.pngjMonkeyEngine (jME) — трёхмерный игровой движок с открытым исходным кодом. Написан на Java и использует по умолчанию LWJGL для рендеринга. Полностью поддерживаются версии OpenGL со второй по четвёртую.Как-то раз упоминался на Хабре в далёком 2010-м году.Помимо характеристик примечателен джавой и не очень примечателен средой разработки NetBeans, которая идёт в комплекте с SDK.

В данной статье хочу рассказать о том, как прикрутить обезьянку к привычной Android Studio.

Создаём новый проект для API не ниже 8 с Blank Activity и в корневой директории проекта создаём папки core и desktop. На языке скриншотов это выглядит как: c521860e23584b71b3bcc7c9f362ba9c.jpg

Подразумеваем, что core — основной код приложения, а desktop и app — запускатели для десктопа и Андроида соответственно.

В корневом settings.gradle указываем эти директории:

include ': app', ': core', ': desktop' Жмём Sync Now в правом верхнем углу окна. Это нужно будет делать при любой модификации gradle-файлов.В директориях core и desktop создаём файл build.gradle: apply plugin: «java» sourceSets.main.java.srcDirs = [«src/»] В корневой build.gradle добавляем репозиторий jmonkeyengine и минимальный набор библиотек для наших подпроектов: buildscript { repositories { jcenter () } dependencies { classpath 'com.android.tools.build: gradle:1.0.0' } }

allprojects { repositories { jcenter () maven { url 'http://updates.jmonkeyengine.org/maven' } } }

project (»: core») { apply plugin: «java» dependencies { compile 'com.jme3: jme3-core:3.0.+' } }

project (»: desktop») { apply plugin: «java» dependencies { compile project (»: core») compile 'com.jme3: jme3-desktop:3.0.+' compile 'com.jme3: jme3-lwjgl:3.0.+' } }

project (»: app») { apply plugin: «android» dependencies { compile project (»: core») compile 'com.jme3: jme3-android:3.0.+' } } После синхронизации в External Libraries должны появится указанные библиотеки со своими соратниками: 6f339aff5782431d9258df3e6565e8ef.jpg

В директориях core и desktop создаём директории src, добавляем в core/src файл Game.java с содержимым из базового примера:

package org.lunapark.dev.jme3example;

import com.jme3.app.SimpleApplication; import com.jme3.material.Material; import com.jme3.math.ColorRGBA; import com.jme3.scene.Geometry; import com.jme3.scene.shape.Box;

public class Game extends SimpleApplication {

@Override public void simpleInitApp () { Box b = new Box (1, 1, 1); Geometry geom = new Geometry («Box», b);

Material mat = new Material (assetManager, «Common/MatDefs/Misc/Unshaded.j3md»); mat.setColor («Color», ColorRGBA.Blue); geom.setMaterial (mat);

rootNode.attachChild (geom); } } Package укажите тот же, что и при создании проекта и вылечите недуги при помощи Alt + Enter и Move to package …: bdbdd64cb55b4ed6be9db0fde7a4faa7.jpg

В desktop/src создаём файл DesktopLauncher.java:

package org.lunapark.dev.jme3example;

public class DesktopLauncher {

public static void main (String[] args) { Game game = new Game (); game.start (); } } Можно запустить DesktopLauncher.java и полюбоваться фантастической трёхмерной моделькой синего кубика. Для запуска на Android заменим код в MainActivity.java на код из примера (обязательно измените значение переменной appClass): package org.lunapark.dev.jme3example;

import android.content.pm.ActivityInfo;

import com.jme3.app.AndroidHarness; import com.jme3.system.android.AndroidConfigChooser;

import java.util.logging.Level; import java.util.logging.LogManager;

public class MainActivity extends AndroidHarness {

public MainActivity () { // Set the application class to run appClass = «org.lunapark.dev.jme3example.Game»;

// Try ConfigType.FASTEST; or ConfigType.LEGACY if you have problems eglConfigType = AndroidConfigChooser.ConfigType.BEST;

// Exit Dialog title & message exitDialogTitle = «Exit?»; exitDialogMessage = «Are you sure you want to quit?»;

// Choose screen orientation screenOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;

// Enable MouseEvents being generated from TouchEvents (default = true) mouseEventsEnabled = true;

// Set the default logging level (default=Level.INFO, Level.ALL=All Debug Info) LogManager.getLogManager ().getLogger (»).setLevel (Level.INFO); } } Дополним AndroidManifest.xml рекомендуемыми параметрами (android: launchMode=«singleTask» и блок «supports-screens»):

Можно запустить app и созерцать кубик уже на телефоне. Если вместо кубика вы созерцаете ClassNotFound Exception и прочее NPE, скорее всего вы забыли поменять переменную appClass в MainActivity.java. Со мной так было.Можно, конечно, в MainActivity.java заменить переменную appClass на

appClass = Game.class.getCanonicalName (); и избавиться от хардкода в переменных для диалога, но какой вы после этого индус, правда? Для использования ресурсов создадим в app директорию assets. Добавим sourceSets { main { assets.srcDirs = ['src/main/assets', 'assets/'] } } в app/build.gradle: apply plugin: 'com.android.application'

android { compileSdkVersion 21 buildToolsVersion »21.1.2»

defaultConfig { applicationId «org.lunapark.dev.jme3example» minSdkVersion 8 targetSdkVersion 21 versionCode 1 versionName »1.0» } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile ('proguard-android.txt'), 'proguard-rules.pro' } } sourceSets { main { assets.srcDirs = ['src/main/assets', 'assets/'] } } }

dependencies { compile fileTree (dir: 'libs', include: ['*.jar']) compile 'com.android.support: appcompat-v7:21.0.3' } Создатели движка рекомендуют такую структуру каталогов:

jMonkeyProjects/MyGame/assets/Interface/ # .font, .jpg, .png, .xml jMonkeyProjects/MyGame/assets/MatDefs/ # .j3md jMonkeyProjects/MyGame/assets/Materials/ # .j3m jMonkeyProjects/MyGame/assets/Models/ # .j3o jMonkeyProjects/MyGame/assets/Scenes/ # .j3o jMonkeyProjects/MyGame/assets/Shaders/ # .j3f, .vert, .frag jMonkeyProjects/MyGame/assets/Sounds/ # .ogg, .wav jMonkeyProjects/MyGame/assets/Textures/ # .jpg, .png; also .mesh.xml+.material, .mtl+.obj, .blend (!) Поддержим товарищей и запихнём для проверки в assets/Textures какую-нибудь небольшую текстуру: c35bbedeb8524bdfb900e74530a154e6.jpg

Заменим код в Game.java:

@Override public void simpleInitApp () { Box b = new Box (1, 1, 1); Geometry geom = new Geometry («Box», b);

Material mat = new Material (assetManager, «Common/MatDefs/Misc/Unshaded.j3md»); TextureKey key = new TextureKey («Textures/poster.jpg»); Texture tex = assetManager.loadTexture (key); mat.setTexture («ColorMap», tex); geom.setMaterial (mat);

rootNode.attachChild (geom); } Запуск приложения на андроид-устройстве должен пройти успешно, в то время как при запуске десктоп-версии ЭВМ выругается злым красным AssetNotFoundException.Отправляемся в desktop/build.gradle и объясняем:

apply plugin: «java»

sourceSets.main.java.srcDirs = [«src/»]

dependencies { compile files (»…/app/assets») } По обычаю, синхронизируем и, с высокой долей вероятности, наблюдаем положительный результат.6d89d706103f4e0bbfdfca17cef310d5.jpg

Если вы не очень хорошо знакомы с jME, то неплохо будет отправиться в раздел Tutorials for Beginners на официальном сайте и пройтись по основам. Или даже скачать сам движок в комплекте с IDE на базе NetBeans, JDK, Блендером и всякими другими полезными штуками.При изучении примеров в корневой build.gradle рекомендую добавить:

project (»: core») { apply plugin: «java» dependencies { compile 'com.jme3: jme3-core:3.0.+'

compile 'com.jme3: jme3-effects:3.0.+' compile 'com.jme3: jme3-networking:3.0.+' compile 'com.jme3: jme3-plugins:3.0.+' compile 'com.jme3: jme3-jogg:3.0.+' compile 'com.jme3: jme3-terrain:3.0.+' compile 'com.jme3: jme3-blender:3.0.+' compile 'com.jme3: jme3-jbullet:3.0.+' compile 'com.jme3: jme3-niftygui:3.0.+'

compile 'net.sf.sociaal: jME3-testdata:3.0.0.20130526' } } Это почти все модули движка плюс ресурсы для примеров (testdata). Полный список модулей на официальном сайте.При разработке под мобильные платформы есть определённые сложности (применение шейдеров, обработка жестов, …), но что-нибудь вполне играбельное можно смастерить если следовать известному крылатому выражению 1899 года. Хотя, наверное, это относится не только к jMonkeyEngine.

Надеюсь, всё это кому-нибудь поможет и никому не навредит.

© Habrahabr.ru