• Что можно приготовить из кальмаров: быстро и вкусно

    Вот скажите, где могут выполняются скрипты написанные на javascript: на сервере, на клиенте? На клиенте, говорите? Это устаревшая информация...

    С введением в Java версии 1.6 Scripting API стало очень просто и удобно писать extension поинты и динамические конфигурации для серверной логики.

    В этой статье я хочу коротко рассказать вам о ScriptEngine, ну и еще кое о чем.

    В частности хочу сделать следующее:

    • На небольшом примере показать, как просто использовать скриптовый движок, встроенный в Java
    • Провести небольшой бенчмаркинг и убедить всех, что скрипты - это не так уж и медленно
    • Неявно рассказать, что JavaScript - один из самых мощных (и недооцененных) языков программирования:)

    Работа со скриптовыми движками производится через интерфейс ScriptEngine. В JDK есть пока что только одна имплементация этого интерфейса - RhinoScriptEngine.

    Сразу небольшой пример кода:

    Public static void main(String args) throws ScriptException { ScriptEngine engine = new ScriptEngineManager().getEngineByName("js"); String helloWorld = (String) engine.eval(""Hello" + " World!""); System.out.println(helloWorld); }

    Мы создаем ScriptEngine через ScriptEngineManager для языка JavaScript. Далее мы выполняем скрипт, суть которого - сконкатенировать 2 строки.

    Как и во многих скриптовых языках, результатом вычисления некоторого куска кода является результат выполнения его последнего оператора. То есть результатом выполнения нашего кода будет строка - "Hello World !".

    В одном проекте перед нашей командой возникла задача - создать механизм для гибкой маршрутизации СМС сообщений в зависимости от разных свойств (дата создания, оператор, номер назначения и т.д.).

    Решено было попробовать движок, который встроен в JDK. Естественно, перед применением новой технологии необходимо проверить ее производительность. Ниже привожу код, который показывает, на что способен движок Rhino (код незначительно упрощен для улучшения понимания):

    Import javax.script.*; public class ScriptBenchmarks { static String script = "sms.serviceNumber == "777" && sms.mobileNumber.startsWith("8050")"; static Sms sms = new Sms(); static int loops = 10000; static void init () { sms.setMobileNumber("80500000000"); sms.setServiceNumber("777"); } // testInitAndEvalInsideLoop average: 1ms static void testInitAnEvalInsideLoop() throws ScriptException { long start = System.currentTimeMillis(); for (int i = 0; i

    Первый метод показывает скорость выполнения скрипта в случае, если движок каждый раз получается через ScriptEngineManager. Во втором методе ScriptEngine создается один раз. В третьем методе происходит создание прекомпилированного скрипта.

    Как вы видите, средняя скорость выполнения скрипта очень мала. Прекомпилированный скрипт не дает большого прироста производительности.

    Надеюсь, статья была вам полезна. Если когда-нибудь вам придется предоставить API для гибкого конфигурирования заказчиком какой-либо логики, вспомните о том, что в JDK уже есть все, что вам нужно.

    На этом, пожалуй, и закончу свое повествование. Жду вопросов и замечаний. Всего вам хорошего.

    Современные движки для 3D-рендеринга, использующиеся в играх и мультимедиа, поражают своей сложностью в плане математики и программирования. Соответственно, результат их работы превосходен.

    Многие разработчики ошибочно полагают, что создание даже простейшего 3D-приложения с нуля требует нечеловеческих знаний и усилий. К счастью, это не совсем так. Более того, при наличии компьютера и свободного времени, можно создать нечто подобное самостоятельно. Давайте взглянем на процесс разработки нашего собственного движка для 3D-рендеринга.

    Итак, для чего же это всё нужно? Во-первых, создание движка для 3D-рендеринга поможет понять, как же работают современные движки изнутри. Во-вторых, сам движок при желании можно использовать и в своём собственном приложении, не прибегая к вызову внешних зависимостей. В случае с Java это значит, что вы можете создать своё собственное приложение для просмотра 3D-изображений без зависимостей (далёких от API Java), которое будет работать практически везде и уместится в 50 КБ!

    Само собой, если вы хотите создать какое-нибудь большое 3D-приложение с плавной анимацией, вам лучше использовать OpenGL/WebGL. Однако, имея базовое представление о том, как устроены подобные движки, работа с более сложными движками будет казаться в разы проще.

    В этой статье я постараюсь объяснить базовый 3D-рендеринг с ортографической проекцией, простую треугольную растеризацию (процесс, обратный векторизации), Z-буферизацию и плоское затенение. Я не буду заострять своё внимание на таких вещах, как оптимизация, текстуры и разные настройки освещения - если вам это нужно, попробуйте использовать более подходящие для этого инструменты, вроде OpenGL (существует множество библиотек, позволяющих вам работать с OpenGL, даже используя Java).

    Примеры кода будут на Java, но сами идеи могут, разумеется, быть применены для любого другого языка по вашему выбору.

    Довольно болтать - давайте приступим к делу!

    GUI

    Для начала, давайте поместим хоть что-нибудь на экран. Для этого, я буду использовать простое приложение, в котором будет отображаться наше отрендеренное изображение и два скроллера для вращения.

    Import javax.swing.*; import java.awt.*; public class DemoViewer { public static void main(String args) { JFrame frame = new JFrame(); Container pane = frame.getContentPane(); pane.setLayout(new BorderLayout()); // slider to control horizontal rotation JSlider headingSlider = new JSlider(0, 360, 180); pane.add(headingSlider, BorderLayout.SOUTH); // slider to control vertical rotation JSlider pitchSlider = new JSlider(SwingConstants.VERTICAL, -90, 90, 0); pane.add(pitchSlider, BorderLayout.EAST); // panel to display render results JPanel renderPanel = new JPanel() { public void paintComponent(Graphics g) { Graphics2D g2 = (Graphics2D) g; g2.setColor(Color.BLACK); g2.fillRect(0, 0, getWidth(), getHeight()); // rendering magic will happen here } }; pane.add(renderPanel, BorderLayout.CENTER); frame.setSize(400, 400); frame.setVisible(true); } }

    Результат должен выглядеть вот так:

    Теперь давайте добавим некоторые модели - вершины и треугольники. Вершина - это просто структура для хранения наших трёх координат (X, Y и Z), а треугольник соединяет вместе три вершины и содержит их цвет.

    Class Vertex { double x; double y; double z; Vertex(double x, double y, double z) { this.x = x; this.y = y; this.z = z; } } class Triangle { Vertex v1; Vertex v2; Vertex v3; Color color; Triangle(Vertex v1, Vertex v2, Vertex v3, Color color) { this.v1 = v1; this.v2 = v2; this.v3 = v3; this.color = color; } }

    В качестве примера я выбрал тетраэдр как простейшую фигуру, о которой вспомнил - нужно всего 4 треугольника, чтобы описать её.

    Код также будет достаточно простым - мы просто создаём 4 треугольника и добавляем их в ArrayList:

    List tris = new ArrayList<>(); tris.add(new Triangle(new Vertex(100, 100, 100), new Vertex(-100, -100, 100), new Vertex(-100, 100, -100), Color.WHITE)); tris.add(new Triangle(new Vertex(100, 100, 100), new Vertex(-100, -100, 100), new Vertex(100, -100, -100), Color.RED)); tris.add(new Triangle(new Vertex(-100, 100, -100), new Vertex(100, -100, -100), new Vertex(100, 100, 100), Color.GREEN)); tris.add(new Triangle(new Vertex(-100, 100, -100), new Vertex(100, -100, -100), new Vertex(-100, -100, 100), Color.BLUE));

    В результате мы получим фигуру, центр которой находится в начале координат (0, 0, 0), что довольно удобно, так как мы будем вращать фигуру относительно этой точки.

    Теперь давайте добавим всё это на экран. Сперва мы не будем добавлять возможность вращения и просто отрисуем каркасное представление фигуры. Так как мы используем ортографическую проекцию, это довольно просто - достаточно убрать координату Z и нарисовать наши треугольники.

    G2.translate(getWidth() / 2, getHeight() / 2); g2.setColor(Color.WHITE); for (Triangle t: tris) { Path2D path = new Path2D.Double(); path.moveTo(t.v1.x, t.v1.y); path.lineTo(t.v2.x, t.v2.y); path.lineTo(t.v3.x, t.v3.y); path.closePath(); g2.draw(path); }

    Заметьте, что сейчас я совершил все преобразования до отрисовки треугольников. Это сделано, чтобы для того, что бы поместить наш центр (0, 0, 0) в центр экрана - по умолчанию начало координат находится в левом верхнем углу экрана. После компиляции вы должны получить:

    Вы можете не поверить, но это наш тетраэдр в ортогональной проекции, честно!

    Теперь нам нужно добавить вращение. Для этого мне нужно будет немного отойти от темы и поговорить об использовании матриц и о том, как с их помощью достичь трёхмерной трансформации 3D-точек.

    Существует много путей манипулировать 3D-точками, но самый гибкий из них - это использование матричного умножения. Идея заключается в том, чтобы показать точки в виде вектора размера 3×1, а переход - это, собственно, домножение на матрицу размера 3×3.

    Возьмём наш входной вектор A:

    И умножим его на так называемую матрицу трансформации T, чтобы получить в итоге выходной вектор B:

    Например, вот как будет выглядеть трансформация, если мы умножим на 2:

    Вы не можете описать любую возможную трансформацию, используя матрицы размера 3×3 - например, если переход происходит за пределы пространства. Вы можете использовать матрицы размера 4×4, делая перекос в 4D-пространство, но об этом не в этой статье.

    Трансформации, которые нам пригодятся здесь - масштабирование и вращение.

    Любое вращение в 3D-пространстве может быть выражено в 3 примитивных вращениях: вращение в плоскости XY, вращение в плоскости YZ и вращение в плоскости XZ. Мы можем записать матрицы трансформации для каждого из данных вращений следующим путём:

    • Матрица вращения XY:
    • Матрица вращения YZ:
    • Матрица вращения XZ:

    И вот здесь начинается магия: если вам нужно сначала совершить вращение точки в плоскости XY, используя матрицу трансформации T1, и затем совершить вращение этой точки в плоскости YZ, используя матрицу трансформации T2, то вы можете просто умножить T1 на T2 и получить одну матрицу, которая опишет всё вращение:

    Это очень полезная оптимизация - вместо того, чтобы постоянно считать вращения на каждой точке, мы заранее считаем одну матрицу и затем используем её.

    Что ж, довольно страшной математики, давайте вернёмся к коду. Создадим служебный класс Matrix3, который будет обрабатывать перемножения типа «матрица-матрица» и «вектор-матрица»:

    Class Matrix3 { double values; Matrix3(double values) { this.values = values; } Matrix3 multiply(Matrix3 other) { double result = new double; for (int row = 0; row < 3; row++) { for (int col = 0; col < 3; col++) { for (int i = 0; i < 3; i++) { result += this.values * other.values; } } } return new Matrix3(result); } Vertex transform(Vertex in) { return new Vertex(in.x * values + in.y * values + in.z * values, in.x * values + in.y * values + in.z * values, in.x * values + in.y * values + in.z * values); } }

    Теперь можно и оживить наши скроллеры вращения. Горизонтальный скроллер будет контролировать вращение влево-вправо (XZ), а вертикальный скроллер будет контролировать вращение вверх-вниз (YZ).

    Давайте создадим нашу матрицу вращения:

    Double heading = Math.toRadians(headingSlider.getValue()); Matrix3 transform = new Matrix3(new double {Math.cos(heading), 0, -Math.sin(heading), 0, 1, 0, Math.sin(heading), 0, Math.cos(heading)}); g2.translate(getWidth() / 2, getHeight() / 2); g2.setColor(Color.WHITE); for (Triangle t: tris) { Vertex v1 = transform.transform(t.v1); Vertex v2 = transform.transform(t.v2); Vertex v3 = transform.transform(t.v3); Path2D path = new Path2D.Double(); path.moveTo(v1.x, v1.y); path.lineTo(v2.x, v2.y); path.lineTo(v3.x, v3.y); path.closePath(); g2.draw(path); }

    Вам также будет нужно добавить слушателей на скроллеры, чтобы обеспечить обновление изображения, когда вы будете тянуть их вверх-вниз или вправо-влево.

    HeadingSlider.addChangeListener(e -> renderPanel.repaint()); pitchSlider.addChangeListener(e -> renderPanel.repaint());

    Как вы, наверное, уже заметили, вращение вверх-вниз ещё не работает. Добавим эти строки в код:

    Matrix3 headingTransform = new Matrix3(new double {Math.cos(heading), 0, Math.sin(heading), 0, 1, 0, -Math.sin(heading), 0, Math.cos(heading)}); double pitch = Math.toRadians(pitchSlider.getValue()); Matrix3 pitchTransform = new Matrix3(new double {1, 0, 0, 0, Math.cos(pitch), Math.sin(pitch), 0, -Math.sin(pitch), Math.cos(pitch)}); Matrix3 transform = headingTransform.multiply(pitchTransform);

    До сих пор мы отрисовывали только каркасное представление нашей фигуры. Теперь давайте заполним его чем-нибудь. Для этого нам нужно сначала растеризовать треугольник - представить его в виде пикселей на экране.

    Я буду использовать очень простой, но крайне неэффективный метод - растеризация через барицентрические координаты. Настоящие 3D-движки используют растеризацию, задействуя железо компьютера, что очень быстро и эффективно, но мы не можем использовать нашу видеокарту, так что будем делать всё вручную, через код.

    Идея заключается в том, чтобы посчитать барицентрическую координату для каждого пикселя, который может лежать внутри нашего треугольника и исключить те, что вне его пределов. Следующий фрагмент содержит алгоритм. Обратите внимание на то, как мы стали напрямую обращаться к пикселям изображения.

    BufferedImage img = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB); for (Triangle t: tris) { Vertex v1 = transform.transform(t.v1); Vertex v2 = transform.transform(t.v2); Vertex v3 = transform.transform(t.v3); // since we are not using Graphics2D anymore, we have to do translation manually v1.x += getWidth() / 2; v1.y += getHeight() / 2; v2.x += getWidth() / 2; v2.y += getHeight() / 2; v3.x += getWidth() / 2; v3.y += getHeight() / 2; // compute rectangular bounds for triangle int minX = (int) Math.max(0, Math.ceil(Math.min(v1.x, Math.min(v2.x, v3.x)))); int maxX = (int) Math.min(img.getWidth() - 1, Math.floor(Math.max(v1.x, Math.max(v2.x, v3.x)))); int minY = (int) Math.max(0, Math.ceil(Math.min(v1.y, Math.min(v2.y, v3.y)))); int maxY = (int) Math.min(img.getHeight() - 1, Math.floor(Math.max(v1.y, Math.max(v2.y, v3.y)))); double triangleArea = (v1.y - v3.y) * (v2.x - v3.x) + (v2.y - v3.y) * (v3.x - v1.x); for (int y = minY; y <= maxY; y++) { for (int x = minX; x <= maxX; x++) { double b1 = ((y - v3.y) * (v2.x - v3.x) + (v2.y - v3.y) * (v3.x - x)) / triangleArea; double b2 = ((y - v1.y) * (v3.x - v1.x) + (v3.y - v1.y) * (v1.x - x)) / triangleArea; double b3 = ((y - v2.y) * (v1.x - v2.x) + (v1.y - v2.y) * (v2.x - x)) / triangleArea; if (b1 >= 0 && b1 <= 1 && b2 >= 0 && b2 <= 1 && b3 >= 0 && b3 <= 1) { img.setRGB(x, y, t.color.getRGB()); } } } } g2.drawImage(img, 0, 0, null);

    Довольно много кода, но теперь у нас есть цветной тетраэдр на экране.

    Если вы поиграетесь с демкой, то вы заметите, что не всё сделано идеально - например, синий треугольник всегда выше других. Так происходит потому, что мы отрисовываем наши треугольники один за другим. Синий здесь - последний, поэтому он отрисовывается поверх других.

    Чтобы исправить это, давайте рассмотрим Z-буферизацию. Идея состоит в том, чтобы в процессе растеризации создать промежуточный массив, который будет хранить в себе расстояние до последнего видимого элемента на каждом из пикселей. Делая растеризацию треугольников, мы будем проверять, меньше ли расстояние до пикселя, чем расстояние до предыдущего, и закрашивать его только в том случае, если он находится поверх других.

    Double zBuffer = new double; // initialize array with extremely far away depths for (int q = 0; q < zBuffer.length; q++) { zBuffer[q] = Double.NEGATIVE_INFINITY; } for (Triangle t: tris) { // handle rasterization... // for each rasterized pixel: double depth = b1 * v1.z + b2 * v2.z + b3 * v3.z; int zIndex = y * img.getWidth() + x; if (zBuffer < depth) { img.setRGB(x, y, t.color.getRGB()); zBuffer = depth; } }

    Теперь видно, что у нашего тетраэдра есть одна белая сторона:

    Вот мы и получили работающий движок для 3D-рендеринга!

    Но и это ещё не конец. В реальном мире восприятие какого-либо цвета меняется в зависимости от положения источников света - если на поверхность падает лишь небольшое количество света, то она видится более темной.

    В компьютерной графике мы можем достичь подобного эффекта с помощью так называемого «затенения» - изменения цвета поверхности в зависимости от угла наклона и расстояния относительно источника света.

    Простейшая форма затенения - это плоское затенение. Этот способ учитывает только угол между поверхностью, нормаль и направление источника света. Вам всего лишь нужно найти косинус угла между двумя векторами и умножить цвет на получившееся значение. Такой подход очень прост и эффективен, поэтому он часто используется для высокоскоростного рендеринга, когда наиболее продвинутые технологии затенения слишком неэффективны.

    Для начала нам нужно посчитать вектор нормали для нашего треугольника. Если у нас есть треугольник ABC, мы можем посчитать его вектор нормали, рассчитав векторное произведение векторов AB и AC и поделив получившийся вектор на его длину.

    Векторное произведение - это бинарная операция на двух векторах, которые определены в 3D пространстве вот так:

    Вот так выглядит визуальное представление того, что делает наше векторное произведение:

    For (Triangle t: tris) { // transform vertices before calculating normal... Vertex norm = new Vertex(ab.y * ac.z - ab.z * ac.y, ab.z * ac.x - ab.x * ac.z, ab.x * ac.y - ab.y * ac.x); double normalLength = Math.sqrt(norm.x * norm.x + norm.y * norm.y + norm.z * norm.z); norm.x /= normalLength; norm.y /= normalLength; norm.z /= normalLength; }

    Теперь нам нужно посчитать косинус между нормалью треугольника и направлением света. Для упрощения будем считать, что наш источник света расположен прямо за камерой на каком-либо расстоянии (такая конфигурация называется «направленный свет») - таким образом, наш источник света будет находиться в точке (0, 0, 1).

    В коде это всё выглядит тривиально:

    Double angleCos = Math.abs(norm.z);

    Мы опускаем знак результата, потому что для наших целей нам не важно, какая сторона треугольника смотрит на камеру. В реальном приложении вам нужно будет отслеживать это и применять затенение соответственно.

    Теперь, получив наш коэффициент затенения, мы можем применить его к цвету нашего треугольника. Простой вариант будет выглядеть как-то так:

    Public static Color getShade(Color color, double shade) { int red = (int) (color.getRed() * shade); int green = (int) (color.getGreen() * shade); int blue = (int) (color.getBlue() * shade); return new Color(red, green, blue); }

    Код будет давать нам некоторые эффекты затенения, но спадать они будут куда быстрее, чем нам нужно. Так происходит, потому что в Java используется спектр цветов sRGB.

    Так что нам нужно конвертировать каждый цвет в линейный формат, применить затенение и затем конвертировать обратно. Реальный переход из sRGB к линейному RGB - довольно трудоёмкий процесс, так что я не буду выполнять полный перечень задач здесь. Вместо этого, я сделаю нечто приближенное к этому.

    Public static Color getShade(Color color, double shade) { double redLinear = Math.pow(color.getRed(), 2.4) * shade; double greenLinear = Math.pow(color.getGreen(), 2.4) * shade; double blueLinear = Math.pow(color.getBlue(), 2.4) * shade; int red = (int) Math.pow(redLinear, 1/2.4); int green = (int) Math.pow(greenLinear, 1/2.4); int blue = (int) Math.pow(blueLinear, 1/2.4); return new Color(red, green, blue); }

    И теперь мы видим, как наш тетраэдр оживляется. У нас есть работающий движок для 3D рендеринга с цветами, освещением, затенением, и заняло это около 200 строк кода - неплохо!

    Вот небольшой бонус для вас - вы можете быстро создать фигуру, приближенную к сфере из своего тетраэдра. Этого можно достичь путём разбивания каждого треугольника на 4 маленьких и «надувая».

    Public static List inflate(List tris) { List result = new ArrayList<>(); for (Triangle t: tris) { Vertex m1 = new Vertex((t.v1.x + t.v2.x)/2, (t.v1.y + t.v2.y)/2, (t.v1.z + t.v2.z)/2); Vertex m2 = new Vertex((t.v2.x + t.v3.x)/2, (t.v2.y + t.v3.y)/2, (t.v2.z + t.v3.z)/2); Vertex m3 = new Vertex((t.v1.x + t.v3.x)/2, (t.v1.y + t.v3.y)/2, (t.v1.z + t.v3.z)/2); result.add(new Triangle(t.v1, m1, m3, t.color)); result.add(new Triangle(t.v2, m1, m2, t.color)); result.add(new Triangle(t.v3, m2, m3, t.color)); result.add(new Triangle(m1, m2, m3, t.color)); } for (Triangle t: result) { for (Vertex v: new Vertex { t.v1, t.v2, t.v3 }) { double l = Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z) / Math.sqrt(30000); v.x /= l; v.y /= l; v.z /= l; } } return result; }

    Вот что должно у вас получиться:

    Я бы закончил эту статью, порекомендовав одну занимательную книгу: «Основы 3D-математики для графики и разработки игр» . В ней вы можете найти детальное объяснение процесса рендеринга и математики в этом процессе. Её стоит прочитать, если вам интересны движки для рендеринга.

    Решил посмотреть, а что собственно есть на эту тему - накопал страницу википедии - само-собой на аглицком языке. Итак начнем! Движки рассматриваются только бесплатные и открытые.

    Agar - написан на C и C++, есть связь с языком Ада, с другими - в разработке. Последнее обновление 30 октября 2008 года.
    - разработан Open Source сообществом на основе исходных кодов игры Marathon 2: Durandal, разработанной компанией Bungie Software в 1995 году. Поддержка основных операционных систем. Есть собственный язык Marathon Markup Language, поддержка Lua. Обновлялся последний раз 22 июля 2008 года.
    Allegro - библиотека для разработки игр. Написана на С/С++, кросплатформенная. Есть связь практически с большинством языков - Ada, C++, C#, D, LISP, Lua,Mercury, Pascal, Perl, Python, Scheme и др.
    Blender GE - ну думаю в представлении не нуждается.
    - движок на основе Doom
    Box2D - кросплатформенный игровой физический движок, написан Erin Catto на С++. Известен тем, что использовался при создании игры Crayon Physics Deluxe (пазлы). Взял премию в IGF (Independent Game Festival).
    CranLib - кросплатформенная объектно-ориентированная библиотека на C++. На форуме сайта видно движение - проект актуальный.
    Crystal Entity Layer - расширение движка Crystal Space
    Crystal Space - хорошая среда разработки. Работают совмество с разработчиками Blender.
    Cube - кросплатформенный движок одноименной игры для создания шутеров.
    DarkPlaces - сильно модифициоранный движок Quake с поддержкой современной графики.
    Delta3D - кросплатформенный, хорошо развивается, свежий релиз вышел совсем недавно.
    Doom - теперь уже открытый и бесплатный движок.
    DXFramework - движок по Win (использует DirectX) для скорее образовательных целей.
    EternityEngine - еще один модифицированный Doom движок.
    открытая реализация популярного движка Ultima IV.
    FIFE - дфижок для создания 2D изометрических игр.
    GZDoom - еще один модифицированный Doom.
    Genesis3D - 3D движок реального времени под Windows
    GenesisDevice - мощный движок, написанный на Object Pascal под Windows платформу.
    Horse3D - маленький и мощный движок.
    - кросплатформенный, написан на С++, поддерживает языки #NET,java, perl, ruby, basic, python, lua, и другие.
    jMonkeyEngine - Java - движок.
    - основанный на Java клиент-серверный движок для создания он-лайн игр типа шашки, шахматы и тд.
    KallistiOS - среда разработки для игровых консолей Dreamcast(tm), Gameboy Advance(tm), Playstation 2(tm), and x86-based компьютеров.
    Lightfeather - кросплатформенный, отличный движок!
    Nebula Device - 3D движок реального времени разработанный студией Radon Labs. Обновлялся в сентябре 2008. Расчитан на Windows, но есть порты на Mac и Linux.
    OGRE Engine - очень популярный обьектно-ориентированный графический движок. Также известен как OGRE3D. Написан на С++. Существует поддержка Windows, Linux и Mac OS.
    ORX - портативный легкий игровой 2D-ориентированный движок. Написан на С с архитектурой плагинов (на С++) - кросплатформенный.
    Panda3D - относительно легкий в использовании python-управляемый игровой движок созданный Carnegie Mellon University . Его использует Disney для производства своих игр.
    RealmForge - движок для.NET
    - движок для создания шутеров от первого лица (Windows).
    Sauerbraten модифицированный кросплатформенный Cube (aka Cube2) движок.
    SDL - библиотека SDL. В комментировании не нуждается.
    SFML простая и быстрая мультимедиа библиотека.
    Spring - мощный игровой движок реального времени.
    - хороший движок для создания 2D игр. В 2007 году разработчики перешли в проект Bos Wars
    Xilon II - непримечательный 2D движок под Visual Basic .NET

    На этом пока бесплатные и открытые движки заканчиваются, но и так видно, что инструментов для создания анимации - пруд пруди и маленькая тележка!

    В следующий раз рассмотрим просто бесплатные движки.

    Обзор бесплатных open-source игровых движков. дата: 08:12 Оценка: 5

    Для кого эта статья: кое-что будет интересно новичкам, которые изучают квест Java Syntax, но в основном изложенный материал лучше зайдёт тем, кто уже перевалил за экватор курса (разбирается с квестами Java Collections и Java Multithreading) и начинает интересоваться технологиями, выходящими за рамки Java Core. За время своего существования Java изрядно обросла библиотеками. Но как понять, какие из них стоит использовать, а какие - нет? Отделить зёрна от плевел вечно занятому разработчику крайне непросто. В этой статье Мартин Пацов (Martin Patsov), Full Stack Developer компании Dreamix, расскажет о своей любви к библиотекам с открытым исходным кодом (open source), и предложит вам те из них, которые считает особенно полезными. Быть иль не быть, вот в чём вопрос: Спасеньем обернётся иль провалом Та самая библиотека Java… Смелей! «СиньйОры» уже были там И опыт их тебе я передам. Пусть вас не вводит в заблуждение моё поэтическое отступление. Библиотек в Java действительно очень много, и разбираться с ними ох как непросто. Тем не менее, я их очень люблю. Меня даже можно назвать «библиотечным евангелистом» (под «евангелистом» в сфере ИТ понимают вовсе не составителя канонический евангелий, а того, кто профессионально пропагандирует ту или иную технологию. Не путайте с обычными пиарщиками: чаще всего ИТ-евангелист досконально разбирается в продвигаемой им технологии. - прим. ред. ). Библиотеки - очень важная часть экосистемы open source. Вокруг них вырастают большие сообщества, которые их развивают и поддерживают. И это здорово. Главное достоинство библиотек в том, что они позволяют нам не изобретать велосипед всякий раз, когда мы пишем код. Используйте библиотеки - уже написанный для определённых задач код - как можно чаще! Вы сэкономите время. Серьезно, лучше потратить его на общение с семьей и друзьями.

    1. Стандартные библиотеки Java

    Да-да, вам не показалась! Очень многие люди недооценивают, более того - не знают массы возможностей - стандартных библиотек Java (Java Standard Libraries), и не в курсе, как раскрыть их потенциал в программировании… а то и вовсе не используют их. Вот краткое описание некоторых из них:
    • java.lang . Эта библиотека всегда импортируется в любое Java-приложение, поскольку содержит всё то, без чего вы в принципе не сможете программировать (String , Double , Enum , Math и так далее).

    • В java.util вы можете найти все коллекции и структуры данных, доступные в Java.

    • Далее, у нас есть java.io для чтения файлов, работающих потоками, объектами класса Pipe и так далее.

    • О первых трёх вы, скорее всего, уже слышали. А вот с java.nio , альтернативой java.io , знают уже не все. Эта библиотека отвечает за неблокирующий ввод-вывод, позволяя, как вы могли догадаться, интенсивно использовать операции ввода-вывода.

    • java.net используется для работы с сокетами, создания подключений или коротких сетевых приложений.

    • В Java у нас также есть библиотеки для работы с GUI: javax.swing (довольно устаревшее расширение ещё более старого java.awt ).

    • Мы даже можем воспроизводить музыку и создавать MIDI-файлы с помощью java.sound .

    2. JHipster

    JHipster - это платформа для быстрого развертывания, разработки и создания масштабируемых веб-серверов с высокой нагрузкой и использованием самых современных и модных технологий таких как Spring, Spring-MicroServices, Netflix,Docker, Kubernetes, AngularJs, Liquibase, MongoDB, Cassandra, ElasticSearch.

    Честное слово, этот «Java-хипстер» определённо спас мне месяцы жизни. Я могу точно сказать, что именно JHipster - мой личный фаворит в списке и он занимает особое место в моем сердце. Этот инструмент - практически незаменим для генерирования эскиза проекта распределенного веб-сервера. Он умеет генерировать pom-файл с зависимостями, настраивать Elastic Search и Connection, вам остается только добавить бизнес-логику архитектуры. Основными и наиболее важными библиотеками, включенными в сгенерированный проект, являются:

    • Spring Boot - помогает ускорить и облегчить разработку приложений
    • Angular / AngularJS - инфраструктура JavaScript
    Здесь вы можете найти больше информации о JHipster .

    3. Maven

    Maven - один из трёх самых популярных инструментов для сборки проектов на Java. Он отвечает за компиляцию, создание jar-файлов (Java-архивов), создание дистрибутива программы, генерацию документации. Структура проекта (зависимости, конфигурации, документация) описывается в файле pom.xml (POM – Project Object Model), который должен находиться в корневой папке проекта. Честно, Maven - просто отличная штука, хоть поначалу и не очень понятная. Если вы никогда не использовали Maven раньше, вы многое потеряли. Откровенно говоря, я вообще не понимаю, как создавались Enterprise-приложения до появления Maven. Почитать о Maven на русском можно .

    4. Apache Commons

    Apache Commons - фактически целый проект, ориентированный на создание библиотек Java. Или «большой набор маленьких Java-утилит» самого разного предназначения. К слову, утилиты Apache Commons лежат в основе нескольких очень известных проектов, например, Tomcat, Hibernate и других. Вот краткий список некоторых из наиболее часто используемых библиотек Apache Commons:
    • Commons Math . Математическая библиотека Apache Commons, имя говорит само за себя: она содержит компоненты для сложных математических и статистических операций и вычислений.

    • Commons CLI . Предоставляет API для анализа аргументов командной строки. Вряд ли стоит даже в мыслях допускать создание приложения без возможности передавать параметры и контролировать его поведение!

    • Commons CSV . Независимо от того, что вы разрабатываете, в какой-то момент вам придется столкнуться с необходимостью использования csv-файлов. То есть, их придётся открывать, читать, редактировать, сохранять и создавать. Я предлагаю использовать формат RFC 4180 из класса CSVFormat и кодировку UTF-8 при сохранении / создании файлов.

    • Commons IO . Используется для упрощения выполнения операций ввода-вывода. Присмотритесь, по крайней мере, к ReversedLinesFileReader, он того стоит!
    Почитать об Apache Commons (на английском) можно .

    5. Guava

    Guava - набор основных библиотек Google для Java. Они содержат новые типы коллекций (например, multimap и multiset), неизменяемые коллекции, библиотеку графов, функциональные типы? утилиты для параллелизма, ввода/вывода, хэширования, обработки строк и многое другое. Все эти инструменты используют специалисты Google в своей работе, а это уже хорошая рекомендация.

    В какой-то мере Guava является альтернативой Apache Commons. На самом деле, о Guava можно говорить долго (обязательно обратите на неё внимание!), но здесь я упомяну только одну полезную штуку из этой библиотеки. Возможно, вы уже сталкивались с задачами упорядочивания своих коллекций или сравнения содержимого в них? А что насчёт расширенной сортировки и сравнения по нескольким столбцам с несколькими условиями? Компонент ComparisonChain используется для реализации расширенной и сложной сортировки для коллекций. Почитать о Guava (на английском) можно .

    6. google-gson

    Библиотека google-gson полезна для преобразования объектов Java в JSON и наоборот. Она особенно пригодится при разработке мобильных приложений и создании/использовании REST API, а также в любом случае, когда вам нужно преобразовать объект Java в его представление JSON и наоборот.
    О JSON (JavaScript Object Notation), Guava, Apache Commons и прочих интересных вещах вы узнаете из квеста .
    Почитать о google-gson (на английском) можно .

    7. Hibernate-ORM

    Hibernate - библиотека, предназначенная для решения задач объектно-реляционного отображения (ORM). Hibernate ORM используется для хранения данных в реляционных базах данных. Она обеспечивает более простой и абстрактный способ сделать это для разработчиков. Он использует JDBC в своей реализации. Hibernate также является реализацией спецификации JPA.

    8. Mockito

    Пусть название Mockito не вводит вас в заблуждение. Речь не о коктейле, а о библиотеке для mock-объектов. Mock-объекты - это объекты, которые имитируют поведение реального объекта по какой-то заданной схеме. Например, для модульного тестирования такие «поддельные» объекты могут симулировать поведение бизнес-объектов. Ну а mock-библиотека Mockito повышает удобство создания и использования mock-объектов.

    Больше информации о

  • Жанровая направленность: 2D/3D игры любого жанра;
  • Платформа: Windows, Linux, Mac, Solaris, Windows CE, FreeBSD, Android и т.д;
  • Лицензия: бесплатная;
  • Языки программирования: Java;
  • Открытый исходный код: предоставляется;
  • Мультиплеер: возможен;
  • Достоинства: кроссплатформенный, оптимизированный, бесплатный, открытый и свободный;
  • Недостатки: не передовые по нынешним меркам графические возможности;
  • Разработчики движка: Helge Foerster.

    jPCT - это свободный 3D-движок для Java, который позволяет использовать OpenGL и Software рендеры на выбор. Данный движок подходит для разработки мощных 3D-приложений для десктопа, Интернета и Android. А небольшие игры на нём пишутся весьма просто и удобно. Движок разрабатывается с 2002 года.

    Для разработки под мобильные устройства на базе операционной системы Android имеется специальный билд движка - PCT-AE (Android Edition). Данный вариант сборки движка заточен под Android, имеет всё те же элементы за исключением некоторых особенностей, которые были устранены или упрощены из-за специфики платформы.

    В jPCT имеется система обнаружения и обработки столкновений - простейшая обработка физики. Имеется возможность подключения библиотек, например, физической библиотеки jBullet, если не хватает простых физических законов.

    Как уже было упомянуто, jPCT поддерживает работу с Software рендером и с OpenGL, что позволяет создавать приложения на разные платформы. Используются аппаратное ускорение, различные режимы экрана и разрешения. Можно использовать Swing/AWT как AWTGLRenderer.

    У движка имеются уже готовые классы для обработки пользовательского ввода. Например, для ввода с клавиатуры используется класс KeyMapper. Вы просто создаете новый объект KeyMapper а потом можете в любое время получить состояние клавиш с помощью вызова poll(). Также jPCT предоставляет классы Object3D, Сamera, World, поддерживает несколько форматов 3D-моделей, удобный их импорт и т.д.

    Получаемые игры можно распространять под нужные вам платформы, например, для отображения в окне браузера можно использовать java-апплет через Java Webstart. Также с минимальными изменениями кода игр их можно портировать под мобильную систему Android. На jPCT разрабатываются игры любой сложности и любого типа. Например, разрабатывается MMORPG "Technopolies", произведён порт "Quake3". Игра работают через LWJGL или JOGL на Windows, MacOS X, Linux (x86) и Solaris. Запускаются и функционируют на Windows CE, FreeBSD, MacOS 9 и на многих других платформах, поддерживающих Java.

    Вместе с движком поставляются необходимые дополнительные материалы: документация и необходимые нативные библиотеки. Получаемые приложения совместимы с Java 1.1 и с прочими старыми виртуальными машинами, типа Microsoft VM и Netscape 4 VM.

    Официальный сайт: http://www.jpct.net




    JPCT is a powerful solution for bringing 3D into the Java world. You want to write a fullscreen game that makes use of hardware acceleration? No problem, jPCT can render into a native (optionally fullscreen) OpenGL window. You may even distribute your game as an OpenGL powered desktop application via Java Webstart and offer an applet version in addition.