Skip to content
GitHub Twitter

игра "INTERVIEW" или как делать текстовые адвенчуры на Phaser

В этой статье я расскажу, как участвовал в джеме Trust No One и сделал текстовую адвенчуру "ITERVIEW" с помощью движка Phaser и скриптового языка Ink.

Поделюсь опытом подключения inkjs, подготовки истории, импорта JSON-файла и рендеринга выбора. Если вы хотите создавать игры с нелинейным сюжетом — будет полезно.

Участие в джеме Trust No One от Плейгамы

Совсем недавно закончился джем от Плейгамы под названием "Trust No One". Я люблю "неторопливые" джемы на пару недель, а тут еще и был шанс заработать денежный приз, хоть сильно я на это не рассчитывал. У джема было два обязательных важных требования: игра должна иметь билд для веба, игра должна иметь встроенный SDK от плэйгамы.

Еще до объявления темы я знал в каком жанре буду делать игру. Мне уже давно очень хотелось сделать текстовую адвенчуру. Прежде я видел на итче и Яндексе пару игр которые мне понравились в реализации, это "The Secret Laboratory" и "Среди зомби". По моему обе игры были сделаны на дефолде с использованием скриптового языка ink, ну и я давно задумывал реализовать похожую по стилю игру но на Phaser.

Игру я в итоге сделал, называется она "ITERVIEW" можно в неё при желании поиграть. А здесь я поделюсь опытом и особенностями подключения ink.js в билд игры на Phaser.

Подготовка истории в редакторе ink

Перед тем Как лезть в Phaser нужно подготовить саму историю с помощью редактора ink. Редактор использует специфический синтаксис, который нужно соблюдать что бы история экспортировалась корректно. Этот синтаксис можно обозначить на простом примере.

Вы заходите в тёмную комнату.
+ [Робко, переступить через порог] -> Начало

= Начало
Поздравляю, вы сделали первый шаг!
+ [Осмотреться] -> Осмотреться
+ [Идти вперёд] -> ИдтиВперёд

= Осмотреться
Вы видите стол и маленькую лампу.
+ [Включить лампу] -> Лампа
+ [Вернуться назад] -> ДвигатьсяДальше

= Лампа
Лампа загорелась. Стало чуть светлее!
-> ДвигатьсяДальше

= ИдтиВперёд
Вы прошли чуть дальше по коридору.
-> ДвигатьсяДальше

= ДвигатьсяДальше
Куда двигаться дальше?
+ [Вперёд] -> ИдтиВперёд
+ [Оглянуться по сторонам] -> Осмотреться

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

После того как работа над рассказом будет закончена, можно экспортировать json с рассказом для использования в игре.

Подключение inkjs и базовое API

Подключается inkjs очень просто через npm

npm install inkjs

а после импортируем модуль в сцену

import { Story } from 'inkjs';

конечно нужно не забыть импортировать json в preload

this.load.json('inkStory', 'assets/story.json');

после читаем его и используем класс Story из inkjs

const data = this.cache.json.get('inkStory');
this.story = new Story(data);

А дальше все просто, проверяя есть ли еще текст для вывода с помощью canContinue и выводя следующий блок текста с помощью Continue() можно выводить блоки текста на экране.

while (this.story.canContinue) {
	textBuffer = this.story.Continue();
}

Варианты ответов можно получить через this.story.currentChoices

this.currentChoices = this.story.currentChoices;
this.currentChoices.forEach((choice, index) => {
	let choiceText = this.add.text(50, 50, choice.text);
});

Добавление картинок на отдельные реплики

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

= Заголовокблока
Текст блока # тег

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

Заключение

Я надеюсь что вам понравился этот урок и вы нашли в нем полезную информацию.

Если у вас есть вопросы ко мне лично, вы можете написать мне в твиттер или телеграм. Так же приглашаю вас в русскоязычное сообщество разработчиков на Phaser.

Если вы решите поддержать меня материально - ссылка на донат.