Как стать автором
Обновить

Пробуем 3D с помощью jMonkeyEngine

Время на прочтение 6 мин
Количество просмотров 28K
Практически каждый, кто занимался геймдевом, понимает, что наилучшей производительности в этой области, по понятным причинам, можно добиться лишь на языках С/С++/asm. С данным утверждением в этой статье я спорить не буду, да и раньше даже как-то не задумывался о создании realtime-игр на других языках. Однако, игры бывают разные, и надо отдавать себе отчёт в том, насколько оправданы трудозатраты на реализацию очередного продукта. Если проект монструозен, с «тяжёлой» графической составляющей, даже после проведения весьма агрессивной оптимизации всё равно требующий от конечных пользователей (геймеров) топового железа на борту, то особых конкурентов на данный момент среди языков разработки у С/С++ в этом случае нету. Но если игрушка — не более чем обыкновенная казуалка, для запуска которой и нетбука будет достаточно, то можно позволить себе куда больший простор для фантазии в вопросе выбора инструментов для разработки. Исходя из этого принципа, в данной статье попробуем разобраться, чем может похвастаться в области геймдева такой, казалось бы, не совсем подходящий для этого, но удобный в целом язык Java, на примере движка jME.

Интро


jMonkeyEngine. Ничего уж тут не поделаешь, движок действительно так называется, и даже слоган на сайте гласит «Serious monkeys. Serious engine» («Серьёзные обезьяны. Серьёзный движок»). У некоторых разработчиков явно что-то завязано на этих животных (вспоминается тот же RenderMonkey для разработки и отладки шейдеров).

Тем не менее, шуточное в движке только название. jME поддерживает всё необходимое для комфортного и достаточно быстрого создания игр, причём не является исключительно графическим визуализатором, т.е. в наличии также имеется система обработки ввода и библиотеки симуляции физики и проигрывания аудио. Помимо стандартного набора инструментов, присущего многим другим движкам, можно отметить такие фичи как:
  • Многопоточность. OpenGL вызовы и игровая логика выполняются в разных потоках. Логика работы может быть реализована с помощью встроенной системы управления игровыми состояниями. Есть несколько предопределённых классов состояний, например, класс TransitionState для реализации экрана загрузки
  • Интеграция в Java Applet, AWT, Swing и SWT
  • Движок работает только со специальным бинарным форматом моделей JME. Тем не менее есть множество конвертеров типа X -> jme (где X == obj, 3ds, и т.д.), которые позволяют импортировать модели из других форматов прямо во время выполнения (нет необходимости заранее переводить созданные модели в формат JME)
  • «Принудительный» контроль за организацией ограничивающих объёмов. При загрузке/создании очередной сеточной модели в коде нужно явно указывать, какой ограничивающий объём будет для неё использоваться
  • Рендеринг Swing компонентов внутри сцены
  • Быстрое математическое ядро, активно использующее таблицы заранее вычисленных значений
  • Встроенные эффекты тип Bloom, Depth Of Field, dot3 bump mapping, Lens Flare, и т.д. Конечно, поддержка GLSL и ARB :)
  • Симуляция тканей
  • www.jmonkeyengine.com/wiki/doku.php/complete_features_list

Установка и простейший пример использования


Загружаем готовый движок, либо сливаем с репозиториев исходники и собираем сами. В обоих случаях на выходе получаем необходимые для работы библиотеки, которые помещаем в любое удобное место на диске.
Теперь создаём пустой проект в Eclipse и заходим в Properties -> Java build path:

image

Тыкаем Add External JARs и добавляем библиотеки из папок /path/to/the/engine/lib (пакеты самого движка) и /path/to/the/engine/lib/lib/lwjgl (пакеты визуализатора, который будет использоваться движком, в данном случае LWJGL). Все пакеты добавлять конечно не обязательно, достаточно только тех, которые будут реально использоваться. Должно получиться примерно так:

image

В свойствах пакетов LWJGL указываем необходимые для их работы native-библиотеки, находящиеся по адресу /path/to/the/engine/lib/lib/lwjgl/native/<ваша_ос>. Например:

image

Первоначальные приготовления завершены, теперь создадим новый класс (Program, например). Сделаем этот класс наследующим классу SimpleGame, который хорошо подходит для тестовых программ, т.к. автоматически настраивает все необходимые параметры и создаёт first-person камеру. Программа будет делать две простые вещи — создавать кубик и загружать модель из .obj файла.
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URL;

import com.jme.app.SimpleGame;
import com.jme.bounding.BoundingBox;
import com.jme.math.Vector3f;
import com.jme.scene.TriMesh;
import com.jme.scene.shape.Box;
import com.jme.util.export.binary.BinaryImporter;
import com.jmex.model.converters.ObjToJme;

public class Program extends SimpleGame
{
  public static void main(String[] args)
  {
    Program game = new Program();
    // При запуске всегда показывать диалог выбора настроек
    game.setConfigShowMode(ConfigShowMode.AlwaysShow);
    game.start();
  }
  
  @Override
  protected void simpleInitGame()
  {
    // Создаём куб
    Box b = new Box("Testbox", new Vector3f(0, 0, 0), new Vector3f(1, 1, 1));
    // Устанавливаем ограничивающий объём
    b.setModelBound(new BoundingBox());
    // Подгоняем его параметры автоматически
    b.updateModelBound();
    // Присоединяем к корневому узлу графа сцены (rootNode присутствует в SimpleGame)
    rootNode.attachChild(b);
    
    // Загружаем модель из .obj файла
    ObjToJme converter = new ObjToJme();
    URL full_mesh_path = Program.class.getResource("mesh.obj");
    TriMesh mesh = null;
    ByteArrayOutputStream output = new ByteArrayOutputStream();
    try
    {
      converter.convert(full_mesh_path.openStream(), output);
      mesh = (TriMesh)BinaryImporter.getInstance().load(output.toByteArray());
    }
    catch (IOException e)
    {
      System.exit(1);
    }
    mesh.setModelBound(new BoundingBox());
    mesh.updateModelBound();
    mesh.setLocalTranslation(Vector3f.UNIT_Y.mult(5));
    rootNode.attachChild(mesh);
  }
}

* This source code was highlighted with Source Code Highlighter.

Ничего сложного. Стоит обратить внимание на строчку

URL full_mesh_path = Program.class.getResource(«mesh.obj»);

Так мы указываем программе искать файл mesh.obj в том же месте, где лежит файл Program.class. Это может быть удобно, например, если игровые ресурсы будут лежать внутри архива .jar, содержащего .class файлы программы.

Теперь программа должна запускаться, выдавать диалоговое окно с выбором графических настроек, создавать окно и отображать в нём вручную созданный кубик и загруженную сеточную модель. В классе SimpleGame реализована возможность отображения статистики времени выполнения, которая включается нажатием F4. Конечно, в реальных проектах подобные дефолтные вещи вряд ли кому-то нужны, поэтому для игр серьёзнее, чем Hello, world, лучше использовать класс StandardGame, или, если подняться ещё выше по иерархии, BaseGame, где придётся всю инициализацию писать самому.

Теперь подготовим программу для распространения. Для этого выполним File -> Export -> Runnable JAR file. В появившемся окне выбираем экспортируемую программу, папку назначения, отмечаем пункт Package required libraries into generated JAR. После нажатия finish имеем файл .jar, содержащий исполняемый код программы и все необходимые библиотеки движка. Для запуска нужно также скопировать native библиотеки из той папки, которую указывали вначале, в папку с программой (например, в ./lib). Для запуска выполняем
java -Djava.library.path=./lib -jar program.jar

Программа сможет загрузить файл mesh.obj, если тот находится либо в папке с program.jar, либо непосредственно в файле program.jar. Добавить файл внутрь архива можно любым архиватором.

Вполне закономерный вопрос тут — а как быстро оно работает?.. На него вполне закономерный ответ — смотрите сами. На сайте есть энное количество демок, загружаемых через jnlp, в том числе не таких примитивных, как этот пример. По ним можно оценить скорость работы.

Финиш


На этом ознакомительную статью можно считать завершённой. Простой пример хорошо показывает лёгкость создания игр с помощью jME. С другой стороны, реальные возможности движка он не раскрывает, зато их раскрывает вики на офф сайте, а также javadoc, так что у заинтересовавшихся впереди простор для творчества и все доступные платформы для покорения.

Work safe. Work smart. Your future depends on it © Half Life railway
Теги:
Хабы:
+26
Комментарии 9
Комментарии Комментарии 9

Публикации

Истории

Работа

Java разработчик
359 вакансий

Ближайшие события

Московский туристический хакатон
Дата 23 марта – 7 апреля
Место
Москва Онлайн
Геймтон «DatsEdenSpace» от DatsTeam
Дата 5 – 6 апреля
Время 17:00 – 20:00
Место
Онлайн