Статьи

Разработка игр для Android с помощью libgdx — Прототип за день, часть 1a

В этой статье я рассмотрю строительные блоки игрового движка и компонентов и покажу, как быстро создать прототип игры, используя библиотеку libgdx .

Что вы узнаете:

  • Создайте очень простую 2D платформу для шутера.
  • Как выглядит законченная игровая архитектура.
  • Как использовать 2D-графику с OpenGL, ничего не зная об OpenGL.
  • Какие разные сущности составляют игру и как они связаны друг с другом в игровом мире.
  • Как добавить звук в вашу игру.
  • Как собрать свою игру на рабочем столе и развернуть на Android — да, это волшебство.

Шаги по созданию игры

  • 1. Есть идея для игры.
  • 2. Нарисуйте несколько сценариев на бумаге, чтобы они напоминали ваше видение и то, как оно будет выглядеть.
  • 3. Проанализируйте идею, переберите несколько версий, настроив ее, и решите, что будет в игре в ее первоначальной версии.
  • 4. Выберите технологию и начните прототипирование.
  • 5. Начните кодировать и создавать ресурсы для игры.
  • 6. Играйте в тесты, улучшайте и непрерывно делайте небольшие шаги к завершению.
  • 7. Польский и релиз!

Идея игры

Поскольку это будет однодневный проект, у него очень ограниченное время, и цель состоит в том, чтобы изучить технологию создания игр, а не сам процесс. Для этого я позволил себе позаимствовать идеи из других игр и сосредоточиться на технических аспектах этого процесса.
Я буду сильно заимствовать из игры под названием Star Guard . Это маленький драгоценный камень, сделанный Vacuum Flowers . Возьми игру и проверь. Очень простой шутер-платформер с упрощенным стилем и ощущением старой школы.
Идея состоит в том, чтобы провести нашего героя через уровни, убивая врагов и уклоняясь от всего, что пытается нас убить.
Управление простое, клавиши со стрелками перемещают героя влево или вправо, Z прыгает, а X стреляет лазером. Чем дольше удерживается кнопка прыжка, тем выше герой прыгает. Он может менять направление в воздухе, а также стрелять. Мы увидим, как мы можем перевести эти элементы управления на Android позже.

Следующие шаги (2 и 3) можно пропустить, так как об этом мы уже позаботимся из-за работающей игры.

Начните свое затмение

Это где мы начинаем. Я буду использовать библиотеку libgdx для создания игры. Почему libgdx? Это лучшая (на мой взгляд) библиотека, которая позволяет легко разрабатывать игры, не зная основополагающих технологий. Это позволяет разработчикам создавать свои игры на рабочем столе и развертывать их на Android без каких-либо изменений. Он предлагает все элементы для использования в играх и скрывает сложность работы с конкретными технологиями и оборудованием. Это станет более очевидным по мере нашего продвижения.

Настройка проекта

Следуя инструкциям из документации libgdx, мы должны сначала загрузить библиотеку.
Перейдите по libgdx-nightly-latest.zip http://libgdx.badlogicgames.com/nightlies/, загрузите файл libgdx-nightly-latest.zip и распакуйте его.

Создайте простой Java-проект в Eclipse. Я назову это star-assault .

Оставьте настройки по умолчанию и, как только проект будет создан, щелкните правой кнопкой мыши по нему и выберите New-> Folder и создайте каталог с именем libs .
Из распакованного libgdx-nighly-latest скопируйте файл gdx.jar во вновь созданный каталог libs . Также скопируйте файл gdx-sources.jar в каталог libs . Он находится в подкаталоге sources в распакованном каталоге gdx. Вы можете сделать это, просто перетащив файлы JAR в ваши каталоги в Eclipse. Если вы копируете их с помощью проводника, или поиска, или любым другим способом, не забудьте обновить ваш проект Eclipse, нажав F5.

Структура должна выглядеть следующим образом:

Добавьте gdx.jar в качестве зависимости от проекта. Сделайте это, щелкнув правой кнопкой мыши название проекта и выбрав Свойства . На этом экране выберите « Путь сборки Java» и перейдите на вкладку « Библиотеки ». Нажмите Add JARs… , перейдите в каталог libs и выберите gdx.jar , затем нажмите OK .

Чтобы иметь доступ к исходному коду gdx и легко отлаживать нашу игру, рекомендуется добавить исходники в файл gdx.jar. Для этого разверните узел gdx.jar , выберите « Вложение источника» , нажмите « Изменить» , затем « Рабочая область»… и выберите « gdx-sources.jar затем « ОК», пока все всплывающие окна не будут закрыты.

Полную документацию по настройке проектов с помощью libgdx можно найти на официальной вики .

Этот проект будет основным проектом для игры. Он будет содержать игровую механику, движок, все. Нам нужно будет создать еще два проекта, в основном пусковые установки для двух платформ, на которые мы нацелены. Один для Android и один для рабочего стола. Эти проекты будут чрезвычайно простыми и будут содержать только зависимости, необходимые для запуска игры на соответствующих платформах. Думайте о них как о классе, содержащем основной метод.

Зачем нам нужны отдельные проекты для них? Поскольку libgdx скрывает сложность работы с базовой операционной системой (графикой, аудио, пользовательским вводом, файловым вводом-выводом и т. Д.), Каждая платформа имеет конкретную реализацию, и нам нужно будет включать только те реализации (привязки), которые требуются целенаправленный. Кроме того, поскольку жизненный цикл приложения, загрузка ресурсов (загрузка изображений, звуков и т. Д.) И другие общие аспекты приложения сильно упрощены, специфичные для платформы реализации находятся в разных файлах JAR, и должны быть включены только те, которые требуются для платформы мы нацелены.

Версия для ПК

Создайте простой Java-проект, как в предыдущем шаге, и назовите его star-assault-desktop . Также следуйте инструкциям по созданию каталога libs . На этот раз необходимые файлы jar из загруженного zip файла:
gdx-natives.jar ,
gdx-backend-lwjgl.jar ,
gdx-backend-lwjgl-natives.jar .
Также добавьте эти файлы jar как зависимости в проект, как в предыдущем проекте. ( щелкните правой кнопкой мыши по проекту -> Свойства -> Путь сборки Java -> Библиотеки -> Добавить JAR , выберите три JAR и нажмите OK .)
Нам также нужно добавить проект star-assault к зависимостям. Для этого перейдите на вкладку Projects , нажмите Add , проверьте проект star-assault и нажмите OK .

Важный! Нам нужно сделать проект star-assault транзитивной зависимостью, означая, что зависимости для этого проекта должны быть зависимостями проектов в зависимости от этого. Для этого: щелкните правой кнопкой мыши по основному проекту -> Свойства -> Путь сборки Java -> Порядок и экспорт -> проверьте файл gdx.jar и нажмите ОК .

Версия для Android

Для этого вам понадобится Android SDK .
Создайте новый проект Android в Eclipse: Файл -> Создать -> Проект -> Проект Android .
Назовите это star-assault-android . Для цели сборки отметьте «Android 2.3». Укажите имя пакета net.obviam или ваши собственные предпочтения. Рядом с «Создать действие» введите StarAssaultActivity . Нажмите Готово .

Перейдите в каталог проекта и создайте подкаталог с именем libs (вы можете сделать это из eclipse). Из nightly zip поместите gdx-backend-android.jar и armeabi и armeabi-v7a во вновь созданный каталог libs .
В eclipse щелкните правой кнопкой мыши проект -> Свойства -> Путь сборки Java -> Библиотеки -> Добавить JAR-файлы , выберите gdx-backend-android.jar и нажмите OK .

Нажмите Add JARs снова, выберите gdx.jar под основным проектом ( star-assault ) и нажмите OK .
Нажмите вкладку Projects , нажмите Add , проверьте основной проект и дважды нажмите OK .
Вот как должна выглядеть структура:

Важный!
Для ADT версии 17 и новее файлы gdx jar должны быть явно помечены для экспорта.
Сделать это
Нажмите на проект Android
Выберите Свойства
Выберите Java Build Path (шаг 1)
Выберите Порядок и Экспорт (шаг 2)
Проверьте все ссылки, например, gdx.jar , gdx.jar gdx-backend-android.jar , основной проект и т. Д. (Шаг 3).
На следующем изображении показано новое состояние.

Также более подробная информация по этому вопросу здесь .

Совместное использование активов (изображения, звуки и другие данные)

Поскольку игра будет одинаковой как для настольного компьютера, так и для Android, но каждая версия должна создаваться отдельно от разных проектов, мы хотим, чтобы изображения, звуки и другие файлы данных находились в общем месте. В идеале это должно быть в основном проекте, так как он включен как в Android, так и в настольную версию, потому что у Android есть строгое правило, где хранить все эти файлы, нам придется хранить там ресурсы. Он находится в автоматически созданном каталоге assets в проекте Android. В eclipse есть возможность связывать каталоги, как в символических ссылках на linux / mac или ярлыках в окнах. Чтобы связать каталог assets из проекта Android с настольным проектом, выполните следующие действия:
Щелкните правой кнопкой мыши проект star-assault-desktop -> Свойства -> Путь сборки Java -> Вкладка « Источник » -> Источник ссылки… -> Обзор… -> перейдите в каталог asssets в проекте star-assault-android и нажмите « Готово» . Вы также можете расширить Переменные … вместо просмотра каталога assets . Рекомендуется, поскольку это делает файловую систему проекта независимой.

Также убедитесь, что каталог assets включен как исходная папка. Для этого щелкните правой кнопкой мыши каталог assets в eclipse (проект рабочего стола), выберите « Путь сборки» -> « Использовать как исходную папку» .

На этом этапе мы готовы к установке и можем продолжить работу над игрой.

Создание игры

Компьютерное приложение — это часть программного обеспечения, которая работает на компьютере. Он запускается, что-то делает (даже если это ничего) и останавливается так или иначе. Компьютерная игра — это приложение определенного типа, в котором часть «делает что-то» заполнена игрой. Начало и конец общие для всех приложений. Также игра имеет очень прямолинейную архитектуру, основанную на непрерывном цикле. Вы можете узнать больше об архитектуре и цикле здесь и здесь.

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

Итак, чтобы настроить нашу игру / игру, нам нужно сделать следующие шаги:

  • 1. Запустите приложение.
  • 2. Загрузите все изображения и звуки и сохраните их в памяти.
  • 3. Создайте сцены для нашей игры вместе с актерами и их поведением (правила взаимодействия между ними).
  • 4. Передайте управление игроку.
  • 5. Создайте движок, который будет манипулировать актерами на сцене на основе входных данных, полученных от контроллера.
  • 6. Определите, когда заканчивается игра.
  • 7. Конец шоу.

Это выглядит довольно просто, и это действительно так. Я буду вводить понятия и элементы по мере их появления.

Для создания игры нам нужен всего один класс.
Давайте создадим StarAssault.java в проекте star-assault . Каждый класс будет создан в этом проекте с 2 исключениями.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package net.obviam.starassault;
 
import com.badlogic.gdx.ApplicationListener;
 
public class StarAssault implements ApplicationListener {
 
 @Override
 public void create() {
  // TODO Auto-generated method stub
 }
 
 @Override
 public void resize(int width, int height) {
  // TODO Auto-generated method stub
 }
 
 @Override
 public void render() {
  // TODO Auto-generated method stub
 }
 
 @Override
 public void pause() {
  // TODO Auto-generated method stub
 }
 
 @Override
 public void resume() {
  // TODO Auto-generated method stub
 }
 
 @Override
 public void dispose() {
  // TODO Auto-generated method stub
 }
}

Просто реализуйте ApplicationListener из gdx и eclipse сгенерирует заглушки для методов, которые должны быть реализованы.
Это все методы, которые нам нужно реализовать из жизненного цикла приложения. Это очень просто, учитывая весь код установки, необходимый для Android или на рабочем столе для инициализации контекста OpenGL, и все эти скучные (и сложные) задачи.

Метод create() вызывается первым. Это происходит, когда приложение готово, и мы можем начать загружать наши активы и создавать сцену и актеров. Подумайте о создании сцены для спектакля в театре ПОСЛЕ того, как все вещи были отправлены туда и подготовлены. В зависимости от того, где находится театр и как вы туда доберетесь, логистика может стать кошмаром. Вы можете отправлять вещи вручную, самолетом или грузовиком … мы не знаем. Мы внутри и все готово, и мы можем начать его собирать. Это то, что libgdx делает для нас. Доставка наших вещей и доставка независимо от платформы.

Метод resize(int width, int height) вызывается каждый раз, когда изменяется размер рисуемой поверхности. Это дает нам возможность переставить биты, прежде чем мы начнем игру. Это происходит, когда размер окна (если игра запускается в одном), например, изменяется.

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

Примечание : для компьютеров окончание игры не эквивалентно окончанию программы. Так что это просто состояние. Программа находится в состоянии игры закончена, но все еще работает.

Конечно, игра может быть прервана во время паузы, и они могут быть возобновлены. Метод pause() будет вызываться всякий раз, когда приложение входит в фоновый режим на рабочем столе или в Android. Когда приложение выходит на передний план, оно возобновляет работу и вызывается метод resume() .
Когда игра завершена и приложение закрыто, вызывается dispose() и пришло время выполнить некоторую очистку. Похоже, когда спектакль окончен, зрители ушли, а сцена демонтирована. Больше не вернусь. Подробнее о жизненном цикле здесь .

Актеры

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

Выявить действующих лиц и персонажей в игре легко.

У нас есть парень (назовем его Бобом — у libgdx есть уроки с Бобом) и блоки, из которых состоит мир.

Сыграв в Star Guard, мы видим, что у Боба несколько состояний. Когда мы ничего не трогаем, Боб бездействует. Он также может двигаться (в обоих направлениях) и прыгать. Также, когда он мертв, он ничего не может сделать. Боб может находиться только в одном из 4 идентифицированных состояний в любой момент времени. Есть и другие штаты, но мы их пока оставим.

Состояния для Боба:

  • Холостой ход — когда не двигается и не прыгает и жив
  • Перемещение — влево или вправо с постоянной скоростью.
  • Прыжки — также лицом влево или вправо и высоко или низко.
  • Мертв — он даже не виден и возрождается.

Блоки — это другие актеры. Для простоты у нас есть только блоки. Уровень состоит из блоков, размещенных в двухмерном пространстве. Для простоты мы будем использовать сетку.
Превратите начало Star Guard в блок и структуру Боба, будет выглядеть примерно так:

Верхний — это оригинал, а нижний — наше мировое представительство.

Мы представили мир, но нам нужно работать в системе мер, в которой мы можем разобраться. Для простоты скажем, что один блок в мире имеет ширину в одну единицу и высоту в одну единицу. Мы можем использовать метры, чтобы сделать его еще проще, но поскольку Боб составляет половину единицы, он делает его на полметра. Скажем, 4 единицы в игровом мире составляют 1 метр, поэтому Боб будет 2 метра.

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

Давайте создадим мир.

Наш главный игровой персонаж — Bob .
Класс Bob.java выглядит следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package net.obviam.starassault.model;
 
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
 
public class Bob {
 
 public enum State {
  IDLE, WALKING, JUMPING, DYING
 }
 
 static final float SPEED = 2f; // unit per second
 static final float JUMP_VELOCITY = 1f;
 static final float SIZE = 0.5f; // half a unit
 
 Vector2  position = new Vector2();
 Vector2  acceleration = new Vector2();
 Vector2  velocity = new Vector2();
 Rectangle  bounds = new Rectangle();
 State  state = State.IDLE;
 boolean  facingLeft = true;
 
 public Bob(Vector2 position) {
  this.position = position;
  this.bounds.height = SIZE;
  this.bounds.width = SIZE;
 }
}

Строки # 16- # 21 определяют атрибуты Боба. Значения этих атрибутов определяют состояние Боба в любой момент времени.
positionposition Боба в мире. Это выражается в мировых координатах (подробнее об этом позже).
acceleration — это будет определять ускорение, когда Боб прыгает.
velocity — будет рассчитана и использована для перемещения Боба.
bounds — каждый элемент в игре будет иметь ограничивающий прямоугольник. Это не что иное, как прямоугольник, чтобы узнать, врезался ли Боб в стену, был убит пулей или выстрелил в противника и ударил. Он будет использоваться для обнаружения столкновений. Подумайте об игре с кубиками.
state — текущее состояние Боба. Когда мы запускаем действие ходьбы, состояние будет WALKING и, основываясь на этом состоянии, мы знаем, что рисовать на экране.
facingLeft — представляет подшипник Боба. Будучи простым 2D-платформером, у нас всего 2 облицовки. Лево и право.

Строки # 12- # 15 определяют некоторые константы, которые мы будем использовать для расчета скорости и позиций в мире. Они будут настроены позже.

Нам также нужны некоторые блоки, чтобы создать мир.
Класс Block.java выглядит следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
package net.obviam.starassault.model;
 
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
 
public class Block {
 
 static final float SIZE = 1f;
 
 Vector2  position = new Vector2();
 Rectangle  bounds = new Rectangle();
 
 public Block(Vector2 pos) {
  this.position = pos;
  this.bounds.width = SIZE;
  this.bounds.height = SIZE;
 }
}

Блоки — это не более чем прямоугольники, размещенные в мире. Мы будем использовать эти блоки для составления ландшафта. У нас есть одно простое правило. Ничто не может проникнуть в них.

примечание libgdx

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

О системе координат и единицах

Как реальный мир, наш мир имеет измерения. Подумайте о комнате в квартире. Он имеет ширину, высоту и глубину. Мы сделаем его двухмерным и избавимся от глубины. Если комната имеет ширину 5 метров и высоту 3 метра, можно сказать, что мы описали комнату в метрической системе. Легко представить размещение стола шириной 1 метр и высотой 1 метр посередине. Мы не можем пройти через стол, чтобы пересечь его, нам нужно запрыгнуть на него, пройти 1 метр и спрыгнуть. Мы можем использовать несколько таблиц, чтобы создать пирамиду и создать несколько странных дизайнов в комнате.

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

Если я бегу со скоростью 10 км / ч, это означает 2,77777778 метров в секунду (10 * 1000/3600) . Чтобы перевести это в мировые координаты Star Assault, скажем, что для скорости 10 км / ч мы будем использовать 2,7 единиц в секунду.

Изучите следующую схему представления ограничивающих рамок и Боба в мировой системе координат.

Красные квадраты — ограничивающие рамки блоков. Зеленый квадрат — это ограничительная рамка Боба. Пустые квадраты — это просто пустой воздух. Сетка только для справки. Это мир, в котором мы будем создавать наши симуляции. Источник системы координат находится внизу слева, поэтому ходьба влево со скоростью 10.000 единиц / час означает, что координата X позиции Боба будет уменьшаться на 2.7 единиц каждую секунду .

Также обратите внимание, что доступ к членам — это пакет по умолчанию, а модели находятся в отдельном пакете. Нам нужно будет создать методы доступа (методы получения и установки), чтобы получить доступ к ним из движка.

Создавая Мир

В качестве первого шага мы просто создадим мир как жестко запрограммированную крошечную комнату. Это будет 10 единиц в ширину и 7 единиц в высоту. Мы разместим Боба и блоки, следующие за изображением, показанным ниже.

World.java выглядит так:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package net.obviam.starassault.model;
 
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Array;
 
public class World {
 
 /** The blocks making up the world **/
 Array<Block> blocks = new Array<Block>();
 /** Our player controlled hero **/
 Bob bob;
 
 // Getters -----------
 public Array<Block> getBlocks() {
  return blocks;
 }
 public Bob getBob() {
  return bob;
 }
 // --------------------
 
 public World() {
  createDemoWorld();
 }
 
 private void createDemoWorld() {
  bob = new Bob(new Vector2(7, 2));
 
  for (int i = 0; i < 10; i++) {
   blocks.add(new Block(new Vector2(i, 0)));
   blocks.add(new Block(new Vector2(i, 7)));
   if (i > 2)
    blocks.add(new Block(new Vector2(i, 1)));
  }
  blocks.add(new Block(new Vector2(9, 2)));
  blocks.add(new Block(new Vector2(9, 3)));
  blocks.add(new Block(new Vector2(9, 4)));
  blocks.add(new Block(new Vector2(9, 5)));
 
  blocks.add(new Block(new Vector2(6, 3)));
  blocks.add(new Block(new Vector2(6, 4)));
  blocks.add(new Block(new Vector2(6, 5)));
 }
}

Это простой контейнерный класс для сущностей в мире. В настоящее время сущностями являются блоки и Боб. В конструкторе блоки добавляются в массив blocks и создается Bob . На данный момент все это жестко запрограммировано.

Помните, что источник находится в левом нижнем углу.

Проверьте остальную часть учебника здесь .

Ссылка: Начало работы в разработке игр для Android с помощью libgdx — создайте рабочий прототип за день — учебное пособие, часть 1, от нашего партнера JCG Impaler в блоге Against the Grain .