как сделать игру новеллу на компьютер

Как сделать игру новеллу на компьютер

__ __ __ __ __ __ __ __

Начните с выбора жанра. Подумайте, будет ли ваша новелла ужастиком, или может симулятором свиданий с хентай сценами? От жанра зависит целевая аудитория новеллы (возраст, пол, люди, принадлежащие к каким-либо обществам и т.п.) Лично я делаю новеллу для подростков и детей моего возраста (11-16 лет). Выбрал я жанр, как вы поняли квест, психология и повседневность. Так же немного хоррора.

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

Когда будет достаточно идей, приступайте к персонажам.

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

Как вы наверное заметили, персонажи в новеллах очень разнообразны и контрастируют между собой. Например беспечная Ульяна и ответственная Славя, или робкая Лена и смелая, бойкая Алиса. Придумайте побольше самых разных персонажей, особенно, если это симулятор свиданийг, или эроге. На выбор но в таком случае будет несколько персонажей, среди которых он может выбрать кого-то и выйти на его рут. Можно также добавить популярных клише, типо родственницы, лоли, лучшая тян в классе, староста тян, можете даже трапа туда закинуть) Главное, чтобы персонажи были раскрытыми и реагировали на ситуацию по разному.
s25608351

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

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

KiriKiri Adventure Game System

Факт: Такие новеллы, как Тук тук литературный клуб, или Бесконечное лето были сделаны на движке ренпай.

Как наверное уже многие заметили, почти ВСЕ новеллы имеют анимешную графику. Поэтому, если хотите иметь прямо очень новельную графику, вам придется научиться рисовать японские мультики. Или же пойти по моим стопам и отклониться от традиции. Я например рисую новеллу в своём стиле (векторный мультяшный лайн-арт мышкой :3).
67938356

Итак, что вам придется отрисовывать? Все игровые элементы, элементы меню, настроек, самой игры на всём её протяжении. Всех персонажей, по нескольким эмоциям на каждого. Также множество фонов. В общем, работы много, но графика есть графика.
s84256582

Кстати, я рисую в sai2.

Да, конечно написать самому музыку, когда тебе на ухо наступил медведь проблематично, но если ты знаешь базовые вещи, например строения тонического, субдоминантного и доминантного аккорда, или из чего состоит простейший бит. Есть множество удобных программ, таких как caustic, fl studio и подобные. Лично я пользуюсь именно ими)

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

Источник

Разработка визуальной новеллы в одно лицо. Слабоумие и отвага или история успеха?

Всем привет. Слабоумный и отважный автор статьи — это я, меня зовут Паша.

Сразу хочу сказать, какие цели преследует эта статья. Во-первых, она должна рассказать о том, как я делал свою игру (с целью какого-никакого пиара, разумеется)). А во-вторых, я хочу спросить совета у пользователей — как можно её попиарить? Сама игра скоро выходит в стиме, а у меня закончились идеи, как это делать(

00008.X9qtdMq

Вот что получилось в итоге.

Но давайте по порядку. История создания визуальной новеллы в одно лицо.

Песнь первая: с какого фига я вообще за это взялся?

Откровенно говоря, я стал инди-разрабом очень неожиданно. Я всегда хотел быть сценаристом, но как-то не сложилось. Вернее, сложилось, но не очень.

В своё время я сделал несколько модификаций для визуальной новеллы (ВН) «Бесконечное лето». Модификации народу понравились, они быстро взлетели на первую страницу рейтинга «за всё время» и до сих пор висят там.Если интересно, то вот ссылка. Такое признание меня взбудоражило и я решил — а почему бы не сделать собственную визуальную новеллу? Тем более я почитал другую визуальную новеллу — «Девушка в Скорлупе 2» и был очень вдохновлён её сюжетом…

00009.J4dpl5cКлассная вещь, кстати. Рекомендую.

В общем, с этого и началась история моего падения)

Песнь вторая: сюжет и сценарий.

Сюжет в моей голове рождался медленно и размеренно. Как я уже сказал — я был очень вдохновлён другой визуалкой. Настолько там закрученный сюжет, персонажи. Прям ух! Соответственно, из щенячьего восторга и выросла идея сделать что-то похожее.

Следующим источником вдохновения стал Джон Константин. Яркий и харизматичный трикстер-экзорцист. У него я позаимствовал конструкцию имени. Моего главного героя будут звать Джон Виктор. Потому что Виктор по-латыни — «победитель». И это можно клёво обыграть в истории.

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

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

Песнь третья: ресурсы.

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

00010.Db2BDQiТак герои выглядели первоначально.

А потом в моём мире наступил экономический кризис и я ушёл с работы. И заказывать графику стало не на что. А раз так — прощай, детектив Виктор, увидимся в следующей жизни. Графики нет, да и у композитора начались какие-то свои проблемы, потому он отказался сотрудничать дальше. (Тем не менее, пару мелодий он написал и они мне понравились — эти треки вошли в финальную версию.)

Но мне повезло. Я наткнулся на японский сайт с готовой графикой. Там продавалось много пресетов по низкой цене и я, не долго думая, затарился сразу по самое «не балуйся». Вопрос с графикой был решён.Правда, оставался вопрос, куда девать предыдущие наработки — всё-таки они делались специально под меня и нравились мне. Увы, частью пришлось пожертвовать. А часть была успешно вставлена в нынешнюю версию.

00005.BEtNh0mТак герой стал выглядеть в итоге.

Вопрос с музыкой решился схожим образом. В стиме был куплен пак мелодий, техподдержке был задан вопрос «а можно это использовать там-то и так-то?» и получен ответ «можно». Ура! Проблема с ресурсами была решена.

Песнь четвертая: код.

Тут надо оговориться. Я — человек не командный, стремлюсь держать всё под контролем, а потому мне гораздо легче сделать всё самому, чем поручить кому-то и в дальнейшем ходить проверять, сделал он или нет.Потому кодить я тоже стал сам.

Читайте также:  как почистить клавиатуру ноутбук леново

С движком RenPy я уже был немного знаком, когда делал модификаций для «Бесконечного лета». Там всё было достаточно лайтово — никакой возни с интерфейсом, размерами шрифтов, оформлением и проч. Просто вставлял текст и менял картинки.И да, напомню ещё раз — я не работал с выборами и переменными.

Тут моя гуманитарная голова начала трещать во второй раз.Прописать развилки на бумаге — это одно. А как их запихнуть в код так, чтобы оно правильно реагировало — это другое.В третьем акте у меня выходило около 16 вариантов развития событий. И эти 16 вариантов складывались из предыдущих выборов.Огромное количество переменных. Все эти «if» «elif», эти флажки и поинты… ой блин.

Но, методом проб, ошибок и какой-то матери, за пару недель я всё это закодил. И, как ни странно, мне понравилось. Видимо, есть во мне какие-то мазохистские черты.Ты что-то делаешь и тут же видишь, как твоя работа воплощается в программе. Прикольно.Также в процессе кода рождалось много интересных идей. А что если персонаж в одном акте спросит имя человека, а в следующем назовёт его по этому имени? А если не спросит — то имени знать не будет? А таких персонажей 7. Здравствуйте, новые переменные.А что, если в ряде сцен экран будет с помехами? Это как раз логично выглядит с учётом сценария. Здравствуйте, эффекты глича и видеошума. А что, если в главное меню запилить ещё кнопку с выводом концовок и сделать одну из них скрытой, доступной только после первого прохождения? А что, если… И всё это реализовывается, и делает игру всё круче и круче.

00007.5S8TakDСпецдеффекты со старой оригинальной графикой.

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

Песнь пятая: провал.

Сначала мне предложил издать игру друг. Он знал о том, что я делаю успехе в модификациях и предложил свои услуги. Я обрадовался и сказал «океюшки!».Но потом ему не понравился ряд моментов и мы разошлись.

Боль. Я стал искать другого издателя. И, кажется, нашёл (тут немножко рекламы) — такой же инди-разраб 7DOTS. Его мне прямо хочется расцеловать в обе щеки и повторять много раз «спасибо-спасибо»)) В первую очередь за то, что он сказал «не, такое оформление не катит» и в одно лицо перефигачил весь дизайн о_О. Кроме того, он добавил пару ЦГ и даже запилил в ВНку слоу-мо сцену (я вообще в шоке, что там так можно).

00004.jTL t9OАнимированная сцена.

Во-вторых, он всё-таки выпустил игру на андроид, где она продавалась за 35 рублей.

Но потом этот разраб-издатель отвалился из-за ряда личных обстоятельств.

Песнь шестая: возрождение из пепла?

Но время шло, я случайно наткнулся на студента-переводчика (вернее, я думаю, что он студент, доказательств у меня нет) и тот согласился перевести проект. Качество, судя по всему, вышло более-менее читабельным. По крайней мере текст понятен. У меня появились некоторые сбережения и я смог оплатить взнос в стиме. Саму игру немного дополнил и подшлифовал, так что версия отличается от торрент-эдишна.

И теперь игра на проверке, страница в стиме есть, я спамлю друзьям «добавьте в вишлист»…

Но что делать ещё? Везде советуют разное. Отправлять кураторам или нет? Искать стримеров или надеяться на бусты стима? Я запутался.

Игроки, разработчики, помогите советом, пожалуйста.

Ну и, конечно же, прошу заценить страницу в стиме — и, если понравится, добавить игру в вишлист.

А вот тут, кстати, сделанный на коленке трейлер. Его я тоже делал сам и это отдельная головная боль.

В общем, моя игра получилась очень многострадальной. Но из-за этого ещё сильнее хочется, чтобы хоть где-то она поимела успех)

На этом пока всё. Надеюсь, вам было интересно читать. И надеюсь, что коллективный разум подкинет клёвых идей.

Источник

Unity + Fungus самый простой способ создать визуальную новеллу

Fungus это бесплатный инструментарий для Unity3D с открытым исходным кодом. Для его использования, вам не потребуются навыки программирования.

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

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

Не забывайте почаще сохранять прогресс.

1) Для начала, нам понадобится скачать установить Unity.

2) Fungus скачиваем из Asset Store

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

4) В созданной вами папке с фонами и персонажами, создаём новую сцену.

5) Заходим в Tools и создаём одного или нескольких персонажей.

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

7) Создаём Flowchart

Чтобы отображалось окно с блок схемой нужно его открыть.

8) Перетаскиваем нужный вам фон.

Кликаем на сознанный блок и даём ему название, при желании.

9) Далее в блоке создаём диалог и прописываем текст выбранному персонажу.

Источник

Движок, скриптовый язык и визуальная новелла — за 45 часов

image loader

Приветствую. Так получилось, что уже три года подряд в качестве подарка на Новый год определенным людям я делаю игру. В 2018-ом году это был платформер с элементами головоломки, о котором я писал на хабре. В 2019-ом — сетевая RTS для двух игроков, о которой я ничего не писал. И наконец, в 2020-ом — визуальная новелла, о которой далее и пойдет речь, созданная в условиях сильно ограниченного времени.

Интересно? Тогда добро пожаловать под кат.

Осторожно: тут много текста и

0. Обоснование разработки движка.

Примечание: Если вам по каким-то причинам неинтересны технические подробности, можете переходить сразу к п. 4 «Разработка игры», однако Вы пропустите основную часть контента

0. Обоснование разработки движка

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

1. Выбор платформы

Выбор, собственно, был невелик: либо Java, либо C++. Недолго думая, я решил реализовывать задуманное на Java, т.к. для быстрой разработки она даёт все возможности (а именно: автоматическое управление памятью и большую, по сравнению с C++, простоту, которая скрывает много низкоуровневых деталей и, как следствие, позволяет меньше акцентировать внимание на самом языке и думать только о бизнес-логике), а также обеспечивает поддержку окон, графики и аудио из коробки.

Для реализации графического интерфейса был выбран Swing, так как я использовал Java 13, где JavaFX уже не входит в библиотеку, а добавлять в зависимости десятки мегабайт OpenJFX было лень. Возможно, это было не лучшим решением, но тем не менее.

Вероятно, возникает вопрос: что это за игровой движок, да без аппаратного ускорения? Ответ заключается в отсутствии времени для борьбы с OpenGL, а также абсолютной её бессмысленности: для визуальной новеллы неважен FPS (во всяком случае, с таким количеством анимации и графики, как в данном кейсе).

2. Архитектура движка и его реализация

2.1 Постановка задачи

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

Под универсальным движком я понимаю движок, поддерживающий относительно низкоуровневые понятия, типа «Игровой объект», «Сцена», «Компонент». Делать было решено именно не универсальный движок, потому что это значительно сократило бы время разработки.

По задумке, игра должна была состоять из следующих частей:

image loader

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

Примечание: Под сценой я понимаю логически выделенную часть игры. Критерием сцены может служить одинаковый фон на протяжении этой самой части.

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

Пожалуй, самым важным желанием было желание писать логику игры не на Java, а на каком-нибудь простом декларативном ЯП.

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

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

2.2. Архитектура и реализация

Учитывая всё вышесказанное, можно поделить движок на три относительно большие части, которые соответствуют одноимённым java-пакетам:

В данном пункте я рассмотрю первые две части. Начну со второй.

Файловая структура квеста следующая:

image loader

Имеется отдельная папка для квеста, в корне которой лежит манифест, а также три дополнительные папки: audio — для звукового сопровождения, graphics — для визуальной части и scenes — для скрипто, описывающих сцены.

Хотелось бы в двух словах описать манифест. Он содержит следующие поля:

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

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

В двух словах о консоли разработчика. Она была разработана по следующим причинам:

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

Его финальная структура имеет следующий вид:

image loader

Из постановки задачи можно сделать вывод, что всё, что придется делать, — это рисовать изображения, рисовать текст, воспроизводить аудио.

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

Объект (с точки зрения ООП), который описывает текст/изображение, назовём дескриптором. То есть для пользователя API движка существуют лишь дескрипторы, которые можно добавить в состояние дисплея и удалить из него. Таким образом, в финальном варианте дисплея имеются следующие дескрипторы (они соответствуют одноименным классам):

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

Игровой цикл выглядит примерно так:

Примечание: Возможно, возникает вопрос «Зачем рендерить поля для ввода, если для них созданы соответствующие текстовые дескрипторы, которые рендерятся на шаг раньше?» На самом деле рендеринга в пункте 7 не происходит — происходит лишь синхронизация параметров InputDescriptor ‘а с параметрами TextDescriptor ‘а — такие как видимость на экране, позиция, размер и другие. Это было сделано, как указывалось выше, по той причине, что пользователь не управляет напрямую соответствующим дескриптору ввода дескриптором текста и вообще о нём ничего не знает.

Стоит отметить, что задание размеров и позиций элементов на экране происходит не в пикселях, а в относительных размерах — числах от 0 до 1 (схема ниже). То есть вся ширина для рендеринга — это 1, и вся высота — это 1 (причем они не равны, о чем я несколько раз забыл и позже пожалел). Также стоило бы сделать, чтобы (0,0) был центром, и ширина/высота были равны двум, но я почему-то про это забыл/не подумал. Однако даже вариант с шириной/высотой равной 1 упрощал жизнь разработчику квестов.

image loader

Пару слов о системе освобождения памяти.

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

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

image loader

3. Скриптовый язык

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

3.1. Язык

Изначально хотелось сделать декларативный язык, в котором нужно было бы лишь указать все необходимые параметры для сцены, и всё. Всю логику бы на себя брал движок. Однако в итоге я пришёл к процедурному языку, даже с элементами ООП (едва различимыми), — и это было хорошим решением, так как, по сравнению с декларативным вариантом, давало возможность многократно большей гибкости игровой логики.

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

Итак, код хранится в текстовых файлах с расширением SSF; каждый файл содержит описание одной либо больше сцен; каждая сцена содержит ноль или больше действий (action); каждое действие содержит ноль или больше операторов.

Возможно, вы жаждете увидеть наконец исходный код на SL, вот он:

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

Ради упрощения такое понятие, как «переменная», в язык не вводилось; как следствие, все значения, используемые в коде, — литералы. В зависимости от типа выделяются следующие литералы:

Название литерала: Примечание:
Строковый литерал Возможность экранирования кавычек и слешей (\\) прилагается, также есть возможность вставить в текст перенос
Целочисленный литерал Поддерживает отрицательные числа
Литерал с плавающей точкой Поддерживает отрицательные числа
None-литерал В коде представлен как none
Булев литерал В коде — on / off для истины/лжи соответственно
Общий литерал Если литерал не подпадает ни под один из вышеперечисленных типов и состоит из букв английского алфавита, цифр и знака нижнего подчеркивания, он общий литерал.

Пару слов про парсинг языка. Имеется несколько уровней «загрузки» кода (схема ниже):

image loader

Теперь вкратце об операторах, чтобы появилось представление о функциональности языка. Изначально имелось 11 операторов, затем в процессе продумывания игры некоторые из них слились в один, некоторые изменились, и добавилось ещё 9 штук. Вот сводная таблица:

Операторы для работы со счётчиками — специфичными для сцены целочисленными переменными.

Была также мысль ввести оператор return (на уровне ядра интерпретатора даже была добавлена соответствующая функциональность), однако я забыл, да он и не пригодился.

В загрузчик скриптов встроено не так много проверок на правильность SL-программы, как хотелось бы. Например, всё, что может выброситься на этапе загрузки скрипта, — это исключение о непредвиденном либо неизвестном токене. Во времени исполнения ситуация лучше: есть проверки на типы аргументов операторов (да-да, операндов), на их количество, на наличие запрашиваемой сущности во время lookup ‘а, возможно, и другие, не помню. Однако нет таких проверок времени загрузки, как вызов только существующих действий или использование только существующих сцен в goto и lookup ‘ах, а также проверки типов аргументов и многих других.

В первую очередь из-за нехватки времени и во вторую — из-за того, что анализаторы всех операторов сделаны через базовый анализатор, который умеет только брать из потока n токенов (представляющих аргументов) и строить объект оператора. При этом никакой проверки на типы аргументов или правильность их содержания не производится, потому что анализатор знает только, что ему нужно забрать из потока n токенов и всё. Проверка происходит позже, в рантайме.

Кратко о диалогах. Приведу синтаксис оператора добавления диалога:

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

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

image loader

Возможно, стоило сделать ещё удаление знаков препинания (знаков вопроса, в частности)

Пример регулярного выражения для диалога, обозначающее «осмотреться»:

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

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

3.2. Интерпретатор

Рассказывать про сам интерпретатор особо нечего: он тоже модульный, модули — это «исполнители» операторов (по одному для каждого). Больший смысл имеет рассказать про специальные действия и смену состояний дисплея.

Для самого SL специальных действий не существует, но для интерпретатора они все-таки есть. Вот они:

Примечание: init и first_come — вместе составляют некое подобие конструктора, что ещё раз намекает на легкий объектно ориентированный оттенок языка.

Это состояние состоит из состояния дисплея и состояния тулкита (обертки, которая добавляет понятие «фон», «основной текст», «поле для ввода» и т. д.). Стало понятно, что нельзя просто выбрасывать эти состояния, а их где-то надо хранить и как-то заменять. Проблема была в том, что все дескрипторы дисплея и тулкита хранились прямо в классах их представляющих (в полях), а сохранять вручную с десяток объектов никоим образом не хотелось.

На помощь пришла композиция и выделение состояния дисплея и тулкита в отдельный класс (что, вероятно, нужно было сделать сразу). Оставалась одна проблема: каким образом заменять состояния с текущего на старое? Ведь нельзя же во время игрового цикла, а именно во время итерации по спискам дескрипторов, просто взять и заменить эти списки. Поэтому тут пришлось добавить метод provideState в дисплей, в который передавался колбэк и состояние для загрузки; а после завершения очередной итерации игрового цикла это состояние заменялось и вызывался колбэк, в котором происходила замена состояния тулкита.

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

4. Разработка игры

Тут я кратко опишу саму игру и процесс её разработки. Как в 2019-м и 2018-м, я решил начать с чего угодно, кроме графики, и начал с истории.

4.1. История и разработка логики игры

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

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

Как оказалось, для разработки задуманной игры мне не понадобилось 25% (5) существующих операторов, а именно: все операторы, связанные со счётчиками; оператор анимирования ( animate ), а также оператор внешнего вызова ( call_extern ).

Помимо основной игры, для ознакомления игроков с кор-механиками игры был разработан демоуровень (скриншот ниже), который состоял из одной сцены (двух, если быть точным, но вторая — просто заглушка, типа «You won»).

image loader

4.2. Графика

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

image loader

Как видно по изображению до ката, рисование не моя стихия, однако нужно было как-то обеспечить хоть какую-то графику на уровне «не отвратительно». Достигнуть его помогли следующие условия:

image loader

image loader

5. Статистика и итоги

На разработку первой версии движка и языка (с 11 операторами) у меня ушло 30 часов 40 минут. На реализацию дополнительных 9 операторов ушло ещё 4 часа 55 минут. Разработка логики непосредственно игры (вместе с демо) потребовала 7 часов 41 минуты. Рисование графики —

4-6 часов (графика не учтена в 45 часах из заголовка).

Примечание: Время кодинга мерялось через расширение «Darkyen’s Time Tracker» для продуктов JetBrains (абсолютно не реклама).
Примечание: Я начал писать это все за 2 дня до Нового года, но не успел — релиз пришлось перенести на Рождество. Так что 45 часов из заголовка были распределены примерно на 8 дней.

Количество чистых строк кода для движка: 4777, для игры (без демо) — 637.

Целью было создать 30 минут игрового времени. В итоге прохождение (с моими подсказками) заняло: демо —

8 минут, основная игра на первую концовку —

24 минуты, на вторую (с быстрым прохождением до момента разветвления) —

8 минут. То есть план был выполнен.

Размер квеста — 232 мегабайта (так много из-за музыки, записанной в WAV).

Было нарисовано 28 изображений (и ещё 3 для демо). Это была моя первая игра с адекватным аудио сопровождением — всего с просторов интернета было скачано и запихнуто в игру 17 единиц звуков/музыки.

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

Очевидное решение — просто выдавать игроку список вариантов того, что он может сделать. Но тут есть и очевидная проблема: вся игра сведется к методичному прокликиванию всех вариантов. Скучно. Поэтому, в итоге после обсуждения был сделан вывод, что максимально приятным и не слишком «открытым» интерфейсом был бы следующий: варианты диалогов даются лишь при диалогах с NPC, а действия с миром производятся мышью, путем клика на определенные участки экрана (например, нажать на куст — обыскать его и т.д.).

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

Ещё один косяк — в демо. Оно было сделано слишком подробным, а именно: найти ключ, вставить ключ, открыть дверь, выйти в неё. В то время как сама игра не была настолько требовательной к описанию каждого действия. Вероятно, это создало у игроков неправильное представление о том, чего ждет от них игра, что, конечно, нехорошо.

Теперь к коду. В целом качество кода меня устраивает (хотя это ещё ни о чём особо не говорит), однако есть следующие моменты:

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

Исходный код движка может быть найден по данной ссылке на GitHub.

Демо и основная игра находится в файлах (assets) в разделе «Releases» для версии «v1.0» там же.

Источник

Поделиться с друзьями
DOMA35.RU - первый компьютерный портал
Adblock
detector