Создание HTML5-игр для самых маленьких(Phaser) Часть 3

Konstantin
Konstantin Ostrovsky
2019-03-06 12:42:25
9

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

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

Анализ

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

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

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

 Сложность игры должна иметь три вариации:

  • просто - низкая скорость реакции соперника;
  • средне - средняя скорость реакции соперника;
  • сложно - скорость соперника и его реакция максимальны, победить его можно лишь при помощи хитростей.

Поддержка мобильных устройств в настоящей версии не предусмотрена.  Но рассматривается в дальнейшей перспективе.

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

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

Прямые конкуренты:

Проектирование

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

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

  • Главное меню;
  • Выбор уровня сложности;
  • Магазин;
  • Игра;

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

Heads-Up Display, аббр. HUD (англ. head-up — предназначенный для просмотра без наклона головы, display — индикация) — часть визуального интерфейса игрока, отображающаяся на фоне виртуального игрового пространства в видеоигре. Название происходит от аналогичного в английском языке обозначения ИЛС.

Иными словами HUD называют элементы визуального интерфейса игрока, которые должно быть всегда видно и они должны оптимально располагаться на экране для быстрого доступа. Такими элементами можно назвать кнопки меню, количество жизней, счет, опыт и прочее. 

Немного забегая вперед, хочу познакомить Вас с таким понятием как ScrollFactor. Как можно заметить этот термин состоит из двух слов scroll (прокрутка) и factor(коэффициент). Другими словами это коэффициент прокрутки. В Phaser 3 у каждого объекта есть свойство ScrollFactor, которое Вы можете задать одноименной функцией. Если указать ему значение ноль - элемент не будет реагировать на прокрутку сцены или смещение камеры, таким образом он всегда будет находиться в одном положении. Это аналогично тому что Вы зададите position:fixed в css.

И тут у некоторых может возникнуть вопрос: "какая еще камера?". Игровая камера - это игровой элемент, определяющий какую часть сцены необходимо отобразить в настоящее время на холсте. Наглядно это выглядит так:

Мы видим что игровая сцена достаточно большая, но в настоящее время на мониторе отображается лишь часть всей сцены, ограниченная размерами камеры. При помощи методов движка Вы можете управлять камерой и двигать ее по осям XYZ, в случае с 2D играми - только по XY.

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

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

Раз уж мы заговорили про анимацию, то давайте обсудим какие виды анимации поддерживает Phaser 3 и рассмотрим два варианта ее реализации.

Метод update

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

Tweens

Много примеров реализации этой анимации Вы можете найти здесь. Этот класс реализует множество всевозможных способов анимации объектов и является встроенным функционалом Phaser 3 для анимации. Полагаю это отличный и наиболее правильный метод анимации объектов, но у него есть ограничения и порой Вам может не хватить его гибкости. Этот метод можно сравнить с методом animate в jQuery. При помощи параметров, переданных в функцию Вы можете создать свою анимацию и запускать ее в нужные моменты времени.

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

В сцене магазина необходимо вывести несколько игровых item'oв, которые являются скинами для персонажа. Каждый item должен иметь стоимость и пользователь должен иметь возможность выбрать item при помощи ввода с клавиатуры.

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

В случае если игрок A пропустил мяч - игроку B начисляется очко и наоборот. Когда количество очков достигает 10 - определяется победитель и игра завершается. 

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

Соберем макет исходя из наших мыслей и вот что получится:

Структура проекта

Прежде чем мы начнем писать игру, давайте более детально рассмотрим структуру проекта. В стартовом шаблоне у нас есть следующие директории и файлы:

  1. assets
  2. src
  3. typescript
  4. index.html
  5. package.json
  6. tsconfig.json
  7. webpack.config.js

1)  assets. Эта папка должна содержать игровые ресурсы, такие как: спрайты, аудио, стили, тайлы и  прочее. Папка не участвует в компиляции проекта и проходит через webpack. Данные остаются в таком виде, в котором Вы их туда загрузили. Каждый тип ресурсов должен находиться в соответствующей под-директории:

  • Изображения - images;
  • Шрифты - fonts;
  • Звуки - audio;
  • Тайлы - tilemaps;
  • Стили - css;

2) src. Исходные файлы игры, такие как: сцены, объекты, классы, константы. Вы можете добавлять свои директории и организовывать хранение на свое усмотрение, но я считаю что такая структура хранения достаточно гибкая и удобна для восприятия. Подробно о каждой под-директории:

  • classes - вспомогательные классы для работы с игровыми элементами и прочим. Здесь вы найдете класс Helper, который имеет один статический метод для сложения. Конечно, этот класс вряд ли Вам пригодиться, он служит лишь примером реализации классов в этой папке. Можете вынести в этот класс методы для отрисовки HUD что бы не дублировать код в каждой сцене;
  • const - константы приложения. В этой папке изначально находится один файл конфигурации для Phaser, который используется в game.ts. Вы можете использовать эти константы не только для определения параметров игры, но и к примеру для проведения расчетов и позиционирования игровых элементов;

  • objects - игровые объекты. Игровым объектом можно считать к примеру противника, мяч, игрока. Каждый из этих объектов имеет свою логику работы и логично будет вынести их в отдельный файл. Большинство разработчиков предпочитают наследовать игровые объекты от уже существующих объектов Phaser. К примеру мяч - это изображение, значит можно наследовать класс Phaser.GameObjects.Image и расширить его, добавив своей логики;
  • scenes - игровые сцены. После создания сцены ее необходимо добавить в соответствующую функцию в файле game.ts для того что бы игра знала про нее. Классы в этой директории наследуются от базового класса Phaser.Scene и расширяют его в случае необходимости.
  • game.ts - основной класс, инициализирующий Phaser.

3) typescript.  TypeScript - отличный язык, но для его правильной работы необходимы заголовочные файлы, которые объяснят интерпретатору какие классы и методы есть у объекта Phaser. В это папке Вы найдете один заголовочный файл для TypeScript. В случае необходимости сюда Вы можете помещать заголовочные файлы других библиотек.

4) index.html. Базовая страница приложения, которая будет открываться после запуска сервера. В случае необходимости Вы можете модифицировать ее под свои нужды.

5) package.json. NPM зависимости проекта.

6) tsconfig.json. Конфигурация для компилятора TypeScript

7) webpack.config.js.  Конфигурация для webpack

 

Другие части статьи: