Построение повествования

В 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.

  1. Команда jump (от англ. прыжок) перемещает повествование в новый лэйбл, не обновляя стэк.
    Пример:
label start:
    "Начало"
    jump next_label # Перемещаемся в next_label...
    "После прыжка" # Сюда повествование не дойдёт, так как этой точки нет в стэке

label next_label:
    "Следующий лэйбл"
  1. Команда call (от англ. вызов) перемещает повествование в новый лэйбл, обновляя стэк, что позволяет вернуться в предыдущий лэйбл командой return.
    Пример:
label start:
    "Начало"
    call next_label # Перемещаемся в next_label...
    "После вызова" # Вместо jump была использована команда call, и этот текст будет выведен читателю

label next_label:
    "Следующий лэйбл"
    return # Возвращаем повествование в лэйбл "start"...
  1. Команда 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() # Стиль пролога
     холодно."
    # ...

Функции и соответствующий им интерфейс:

  1. Пролог ($ prolog_time())

Диалоговое окно Стрелка назад Стрелка вперёд

  1. День ($ day_time())

Диалоговое окно Стрелка назад Стрелка вперёд

  1. Закат ($ sunset_time())

Диалоговое окно Стрелка назад Стрелка вперёд

  1. Ночь ($ night_time())

Диалоговое окно Стрелка назад Стрелка вперёд

Изменение оттенка спрайтов

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

Пример:

    # ...
    show sl normal pioneer
    $ persistent.sprite_time = "day" # Дневной оттенок (без оттенка)
    pause
    $ persistent.sprite_time = "sunset" # Утренний/вечерний оттенок
    pause
    $ persistent.sprite_time = "night" # Ночной оттенок
    pause
    # ...
  1. Цвет дневного оттенка — #FFFFFF.

Спрайт пионера

  1. Цвет утреннего/вечернего оттенка — #EFD1FF.

Спрайт пионера

  1. Цвет ночного оттенка — #A0C6D1.

Спрайт пионера

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

Как такового "прологового" оттенка в игре нет: в эпилоге (где используется прологовый стиль интерфейса) использован ночной оттенок.

Изменение режима повествования

Как вы уже, наверное, знаете, в базовой игре существует два режима вывода текста. Называются они ADV- и NVL-режимами.
В ADV-режиме (от англ. AdventureПриключение) на экране отображается по одной реплике в отдельном окне диалога. Также в этом режиме реплики часто сопровождаются визуальными и звуковыми эффектами. Этот режим всегда включён по умолчанию.
В NVL-режиме (от англ. NovelНовелла) на экране может находиться большое количество реплик.

Пример:

    # ...
    $ set_mode_adv() # Ещё раз напоминаем, что ADV-режим стоит по умолчанию!
    "Короткая фраза."
    $ set_mode_nvl() # Изменяем на NVL-режим...
    "Lorem ipsum dolor sit amet..." # А здесь уже можно писать длинный текст
    # ...

Смена режимов повествования таким образом работает только для ванильных и наследуемых от них персонажей!

О том, как создать NVL-персонажа, вы можете прочесть в этой статье.

Список всех ванильных персонажей вы можете найти на этой странице.

Больше информации

Получить больше информации о повествовании вы можете на странице официальной документации Ren'Py.

Источники

1^

Оригинальный. См.: Глоссарий / Ваниль.