Построение повествования
В Ren'Py повествованием называется процесс описания и представления игроку происходящих в сюжете произведения событий. Всё повествование происходит в отдельных Ren'Py-блоках, называемых лэйблами, и в основном состоит из вывода реплик, манипуляций над изображениями, проигрывания аудио и прочих действий.
label day3_main2: # game\scenario\day3.rpy:311
window show
"Я дожёвывал сосиску, которая больше напоминала кусок витой пары."
me "Интересно, есть у них здесь интернет?"
me "Откуда?"
"Пионер за соседним столом заметил, что я разговариваю сам с собой, покосился на меня, а я в ответ улыбнулся и помахал ему рукой."
"После такого дружелюбного приветствия он почему-то быстрыми шагами покинул столовую, даже не доев завтрак."
stop ambience fadeout 2
th "С едой покончено – самое время отправиться на поиски разгадок."
window hide
Лэйблы
Лэйблы (или просто метки, от англ. Label) — это именованные точки, которые позволяют повествованию перемещаться в конкретные места в сюжете.
Синтаксис:
label <Название лэйбла>:
<Дальнейшие команды> # Все дальнейшие команды могут быть написаны без отступа в начале, но мы не рекомендуем этого делать.
Во избежание конфликтов имя каждого лэйбла должно быть уникальным и отличаться от всех остальных.
В больших модах название лэйбла часто состоит из названия сцены или номера дня/главы/эпизода/прочего и постфикса или префикса в виде короткого названия мода.
Пример:
mymod_day2
↑ ↑ Название сцены
│ Префикс (в виде названия мода)
Или...
day2_mymod
↑ ↑ Постфикс (в виде названия мода)
│ Название сцены
Вы можете использовать кириллицу в названиях лэйблов, но в сообществе это считается плохой практикой и строго не рекомендуется.
Глобальные и локальные лэйблы
Ранее показанные лэйблы являются глобальными, и вызвать их можно из любой части игры.
Но помимо глобальных существуют и локальные лэйблы.
Они всегда принадлежат своему глобальному лэйблу и не могут существовать без него.
Синтаксис:
label <Название глобального лэйбла>:
<Команды>
label .<Название локального лэйбла>: # Краткое написание, принадлежит первому найденному глобальному лэйблу
<Команды>
label <Название глобального лэйбла>.<Название локального лэйбла>: # Полное написание, принадлежит глобальному лэйблу перед точкой
<Команды>
Если повествование находится в глобальном лэйбле с подконтрольными ему локальными лэйблами, то на них можно перемещаться, используя только название локального лэйбла.
Пример:
label global_label:
"Внутри этого глобального лэйбла есть..."
jump .local_label
label .local_label:
"...локальный лэйбл!"
Также можно переместиться в локальный лэйбл другого глобального лэйбла.
Для этого нужно использовать связку в виде названия глобального лэйбла и названия локального лэйбла, разделённых точкой.
Пример:
label global_label:
"Мы в глобальном лэйбле."
jump another_global.local_label
label another_global:
"Учите английский язык!"
label .local_label:
"А теперь мы в локальном лэйбле другого глобального лэйбла."
Перемещение между лэйблами
Далее в статье будет использован такой термин, как стэк.
Стэк можно описать как список точек, с которых продолжится повествование после того, как оно дойдёт до команды return.
Каждая команда call добавляет такую точку после себя, а команда return возвращает повествование на последнюю такую точку и удаляет её из стэка.
Если точек в этом списке не осталось и повествование доходит до команды return, то игра перезапускается, что создаёт эффект возвращения в главное меню.
Для перемещения между лэйблами существует три команды: jump, call и return.
- Команда
jump(от англ. прыжок) перемещает повествование в новый лэйбл, не обновляя стэк.
Пример:
label start:
"Начало"
jump next_label # Перемещаемся в next_label...
"После прыжка" # Сюда повествование не дойдёт, так как этой точки нет в стэке
label next_label:
"Следующий лэйбл"
- Команда
call(от англ. вызов) перемещает повествование в новый лэйбл, обновляя стэк, что позволяет вернуться в предыдущий лэйбл командойreturn.
Пример:
label start:
"Начало"
call next_label # Перемещаемся в next_label...
"После вызова" # Вместо jump была использована команда call, и этот текст будет выведен читателю
label next_label:
"Следующий лэйбл"
return # Возвращаем повествование в лэйбл "start"...
- Команда
return(от англ. возврат) удаляет последнюю точку из стэка и возвращает повествование к ней. Если стэк пуст — возвращает игрока в главное меню.
Пример:
label start:
"Начало"
call next_label # Перемещаемся в next_label...
"После вызова"
return # Стэк пуст! Возвращаем игрока в главное меню...
label next_label:
"Следующий лэйбл"
return # Возвращаемся к последнему лэйблу в стэке...
Если в конце лэйбла не стоит команда return, то повествование пойдёт дальше и достигнет следующего лэйбла.
Если же после конца лэйбла нет других лэйблов, то игра закончится, и игрок вернётся в главное меню.
Пример:
label start:
"Начало"
# Здесь ничего не осталось, дальше только следующий лэйбл
label next_label:
"Следующий лэйбл" # А после этой команды ничего нет, и игрока вернёт в главное меню
Вывод реплик
Чтобы вывести какую-либо реплику какого-либо персонажа, в повествовании используется внутренняя команда, которая состоит из двух частей: вызываемого объекта персонажа (или имени персонажа строкой) и самой реплики.
"<Реплика>"
"<Имя персонажа>" "<Реплика>"
<Вызываемый объект> "<Реплика>"
Примеры:
# ...
"Привет!" # На экран выведется текст "Привет!" без имени персонажа
"Персонаж" "Привет!" # На экран выведется текст "Привет!" от персонажа "Персонаж"
sl "Привет!" # На экран выведется текст "Привет!" от Слави
# ...
Если в команду передана только одна строка текста, то она будет восприниматься как реплика от внутреннего персонажа narrator — рассказчика, у которого нет видимого имени.
Чаще всего для удобства для каждого персонажа создаётся переменная, в которой и хранится его объект. О том, как создавать новых персонажей, читайте в этой статье.
Узнать, какие переменные отвечают за каких персонажей, можно на странице с ресурсами оригинальной игры.
Продолжение реплики
Чтобы продолжить предыдущую реплику, используется персонаж extend.
Предыдущая реплика останется на экране, а следующая начнёт выводиться сразу же после неё.
Пример:
# ...
"Я и не думал, что такое может быть."
extend " Но это может быть."
# ↑ Заметьте! Пробел!
# ...
Имейте в виду, что между репликами должен стоять пробел или перенос на следующую строку (\n), без них в итоговой реплике не будет пробела!
Пробел должен стоять в конце предыдущей реплики или в начале extend'а.
# ...
"Я и не думал, что такое может быть."
extend "Но это может быть."
# ...
Получится:
Я и не думал, что такое может быть.Но это может быть.
Отображение и скрытие диалоговых окон
Диалоговые окна (так же, как и окна NVL-режима) можно отображать и скрывать перед выводом реплики. Это также можно делать плавно, используя переходы.
Чтобы отображать и скрывать диалоговое окно, используются команды window show и window hide соответственно.
К отображению и скрытию диалоговых окон можно применить переходы, если сразу после команды указать объект перехода.
Пример:
# ...
"Я выглянул в окно."
window hide dissolve # Заметьте, что здесь не требуется ключевое слово with
# ...
window show dissolve
"Я сел обратно за стол."
# ...
Чтобы отображать и скрывать окно NVL-режима, используются команды nvl show и nvl hide соответственно.
Так же, как и с диалоговыми окнами, к отображению и скрытию окон NVL-режима можно применить переходы, если сразу после команды указать объект перехода.
Помимо отображения и скрытия, окно NVL-режима можно очистить командой nvl clear.
Пример:
# ...
"Бла-бла-бла."
"Бла-бла-бла-бла."
"Бла-бла."
nvl clear # Все предыдущие реплики пропадут с экрана NVL-режима
"Бла."
# ...
Особые функции повествования
В Бесконечном Лете в повествовании можно изменять и некоторые другие параметры игры: изменять стиль интерфейса, оттенок спрайтов или включать NVL-режим для ванильных1 персонажей.
Изменение стиля интерфейса
При использовании стандартного интерфейса новеллы во время повествования можно изменить его стиль. Для этого в повествовании нужно вызвать функцию смены интерфейса.
Пример:
# ...
$ day_time() # Дневной стиль интерфейса
"Днём было светло."
$ sunset_time() # Утренний/вечерний стиль
"Но день подходил к концу."
$ night_time() # Ночной стиль
"А ночью было темно."
$ prolog_time() # Стиль пролога
"И холодно."
# ...
Функции и соответствующий им интерфейс:
- Пролог (
$ prolog_time())
- День (
$ day_time())
- Закат (
$ sunset_time())
- Ночь (
$ night_time())
Изменение оттенка спрайтов
При использовании стандартных спрайтов новеллы во время повествования можно изменить их оттенок. Для этого в повествовании нужно изменить постоянную переменную "времени спрайтов".
Пример:
# ...
show sl normal pioneer
$ persistent.sprite_time = "day" # Дневной оттенок (без оттенка)
pause
$ persistent.sprite_time = "sunset" # Утренний/вечерний оттенок
pause
$ persistent.sprite_time = "night" # Ночной оттенок
pause
# ...
- Цвет дневного оттенка —
#FFFFFF.
- Цвет утреннего/вечернего оттенка —
#EFD1FF.
- Цвет ночного оттенка —
#A0C6D1.
Смена оттенка не распространяется на некоторые спрайты оригинальной новеллы и на все пользовательские спрайты! Их нужно будет красить самому или добавлять проверки, как в оригинальной новелле! Пример покраски спрайта с проверкой можно найти в файлах скриптов игры.
Как такового "прологового" оттенка в игре нет: в эпилоге (где используется прологовый стиль интерфейса) использован ночной оттенок.
Изменение режима повествования
Как вы уже, наверное, знаете, в базовой игре существует два режима вывода текста. Называются они ADV- и NVL-режимами.
В ADV-режиме (от англ. Adventure — Приключение) на экране отображается по одной реплике в отдельном окне диалога.
Также в этом режиме реплики часто сопровождаются визуальными и звуковыми эффектами.
Этот режим всегда включён по умолчанию.
В NVL-режиме (от англ. Novel — Новелла) на экране может находиться большое количество реплик.
Пример:
# ...
$ set_mode_adv() # Ещё раз напоминаем, что ADV-режим стоит по умолчанию!
"Короткая фраза."
$ set_mode_nvl() # Изменяем на NVL-режим...
"Lorem ipsum dolor sit amet..." # А здесь уже можно писать длинный текст
# ...
Смена режимов повествования таким образом работает только для ванильных и наследуемых от них персонажей!
О том, как создать NVL-персонажа, вы можете прочесть в этой статье.
Список всех ванильных персонажей вы можете найти на этой странице.
Больше информации
Получить больше информации о повествовании вы можете на странице официальной документации Ren'Py.
Источники
Оригинальный. См.: Глоссарий / Ваниль.














