Руководство по созданию мода для Бесконечного Лета от Gubaew_R
Простое руководство для интересующихся, о том, как же, всё таки, создать свой мод для Бесконечного Лета.
Предисловие
У всех свои причины, по которым они решили создать свой собственный мод для Бесконечного Лета. Так что эту тему особенно развивать не будем.
Прежде чем создавать мод, убедитесь, что у вас есть: время, желание, усидчивость, минимальное знание английского, хоть какое-то понимание программирования в целом, и самое главное — достойная идея. Без этого ваш мод, к сожалению, будет бесперспективен.
Кроме того, вам очень пригодится художник. Без него можно обойтись, если вы создаёте переделку оригинальной истории, или будете втихую тырить с согласия автора одалживать картинки из других модов.
При создании мода появляется множество нюансов, из-за которых легко можно забросить это дело. Готовьтесь и к этому.
Глава 1: init — Самое начало
Для начала заходим в папку mods, которая находится по пути:
…SteamsteamappscommonEverlasting Summergamemods
Где три точки — диск и расположение папки Steam. У всех оно разное.
Если вы не сможете разобраться с этим этапом, то боюсь представить, что будет дальше…
В этой папке создаём свою папку, которая будет называться также как и рабочее название мода. Желательно на латинице.
Заходим в неё, и предварительно создаём папки: ambience, bg, cg, music, sound, sprite, video. В этих папках будут спрятаны все необходимые материалы для мода.
Всяко лучше, чем если бы они были раскиданы в одной папке, верно?
Далее создаём два текстовых файла с расширением .rpy
Если у вас скрыты расширения файлов, то исправьте это. Интернет в помощь =)
Эти файлы можно назвать как угодно, но я рекомендую назвать первый как:<название_вашего_мода>_materials (test_mod_materials), ведь в нём мы запишем все материалы для мода, чтобы они не мешали нам писать сценарий.
А второй по названию мода, или дня/события/ветки, в общем — как вам будет угодно. Позже название всегда можно изменить.
Для работы с ними нам понадобится блокнот, или любая подобная программа.
У меня вот Notepad++.
Открываем файл с материалами, и пишем в самом начале “init:“, без кавычек.
Кстати, кодировка файла должна быть Юникод (UTF-8), ANSI не поддерживается движком.
На следующей строке нажимаем 4 раза на пробел, или один раз на Tab.
Но тут важное примечание: движок игры не поддерживает табуляцию (Tab), из-за чего вам придётся постоянно их переделывать в пробелы. Желательно с помощью встроенных функций, как например в Notepad++. Чтобы сделать это в нём выделяете весь текст с помощью комбинации клавиш Ctrl + A, затем нажимаете сверху на кнопку Правка > Операции с пробелами > Табуляцию в пробел. Для удобства сделайте соответствующий макрос (для прошареных).
Так вот. Мы сделали 4 пробела, или один Tab. Мы сформировали блок. Пишем там:
$ mods[“рабочее_название_мода”]=u”Название_мода”
Именно в такой форме. Где рабочее_название_мода пишем название вашей папки и первого лейбла (его создаём далее, об этом ниже), где Название_мода, то название которое будет отображаться в игре и в мастерской.
Получается примерно так:
Эта часть будет писаться в каждом файле связанным с модом, и она везде должна быть абсолютно одинаковая. Иначе у вас будет несколько модов в одном… А что, это удобно!
Мы пишем init в файле, чтобы игра зарегистрировала его. Так что, если в файле нет блока init, игра даже не будет его читать. Не говоря уже о том, чтобы показать ваш мод в самой игре.
Материалы
В этом разделе мы сразу распишем всё, что нужно для того, чтобы ваши пользовательские материалы оказались в игре.
Если у вас таковых нет, переходите к следующему разделу о переменных.
Для начала раскидайте все свои файлы по созданным ранее папкам. Затем мы рассмотрим как прописать их в игру.
Чтобы добавить своего персонажа (без тени у имени) в историю, пишем следующий код:
$ тэг_персонажа = Character (u’имя_персонажа‘, color=”цвет_имени“, what_color=”цвет_текста“)
- Где тэг_персонажа, пишем на латинице те инициалы, которыми вы будете быстро вызывать данного персонажа при написании его речи. Желательно не больше двух-трёх букв.
- Где имя_персонажа, пишем отображаемое в игре имя. Желательно только имя или имя с фамилией/отчеством. Так как три слова скорее всего не влезут в область имени.
- Где цвет_имени, пишем код цвета выбранного вами в формате HEX (регистр не важен). Его можно взять в палитре цветов на различных сайтах в интернете, или фото-редакторах, как Photoshop. Этим цветом будет отображаться в игре имя вашего персонажа.
- Где цвет_текста, либо пишем стандартный цветffdd7d, либо любой другой, тоже в формате HEX. Этим цветом будет отображаться речь персонажа.
У такого персонажа не будет тени у имени. Это печально. Посмотрим что можно сделать с этим, ниже.
$ тэг_персонажа = Character (u’имя_персонажа‘, color=”цвет_имени“, ctc=”ctc_animation”, ctc_position=”fixed”, what_color=”цвет_текста“, drop_shadow = [ (2, 2) ], drop_shadow_color = “#000”, what_drop_shadow = [ (2, 2) ], what_drop_shadow_color = “#000”)
Отличия этого кода только в том, что здесь прописана тень. Все остальные пункты прописываются как было показано выше.
Получается что-то такое:
Как фоны (bg) так и красивые картинки (cg) прописываются таким кодом:
image название_изображения = “путь_к_изображению“
- Где название_изображения, пишем рабочее название картинки.
- Где путь_к_изображению, пишем путь к этому файлу:
mods/название_вашего_мода/bg_или_cg/картинка.png
Музыка, звуки, эмбиент — всё это пишется одним и тем же кодом:
$ название_аудио = “путь_к_файлу”
Что где писать, смотрите на пункт выше. Ибо всё работает по той же системе.
Тут уже сложнее. Думаю вы знаете, что спрайты в БЛ это те изображения, которыми показываются персонажи. Те что ещё умеют менять одежду и эмоции. Чтобы их прописать можно написать, либо такой же код, что и у изображений, либо специальный:
image тэг_персонажа эмоция другие_значения = ConditionSwitch(
“persistent.sprite_time==’sunset’”,im.MatrixColor( “mods/ваш_мод/sprite/тэг_персонажа/спрайт.png“, im.matrix.tint(0.94, 0.82, 1.0) ),
“persistent.sprite_time==’night’”,im.MatrixColor( “mods/ваш_мод/sprite/тэг_персонажа/спрайт.png“, im.matrix.tint(0.63, 0.78, 0.82) ),
True, “mods/ваш_мод/sprite/тэг_персонажа/спрайт.png” )
Плюс специального в том, что у изображений прописанных этим кодом может меняться освещение, которое мы тоже обсудим позже.
Когда будете писать этот код, обратите внимание на тэг_персонажа, и необходимость прописывать путь к спрайту три раза. Тэг нужен для того, чтобы при необходимости сразу же скрывать спрайт, не расписывая все его характеристики, и для того, чтобы менялся сам спрайт, один на другой, а не показывался один поверх другого.
Будем откровенны, именно так и прописываются большинство спрайтов, ибо первый способ — мазохизм.
ВНИМАНИЕ! После публикации мода все пути к материалам необходимо изменить, удалив mods/название_вашего_мода/, иначе ваши материалы не будут обнаружены игрой.
Но об этом позже.
Изначальные переменные
Кроме пользовательских материалов в наш файлик materials мы запишем переменные.
Переменные — это некие значения, которые могут измениться в процессе игры.
У нас есть два типа переменной: True or False и числительное значение.
True or False работает по типу: Да или Нет.
Числительное значение — это любое число, включая отрицательные.
Не забываем про 4 пробела, они пишутся всегда. Исключения только init и label.
Записываются они довольно просто:
$ название_переменной = True_или_False
Как вы поняли, если значение переменной Да или Нет, то пишем True, если Да, и False, если Нет.
То есть у вас получится что-то такое:
Переменные очень полезные. Они могут обозначить наличие какого-то условия при событии, и количество “очков отношений“, на которых и строится всё Бесконечное Лето, да и другие Визуальные Новеллы.
Сейчас мы прописали изначальные значения переменных. Без них, переменные не смогут измениться, что вполне логично. Ведь изменяться будет нечему, дошло?)
О том, как же их изменять, и как они могут влиять на историю, поговорим ниже.
Глава 2: label — Как начать писать
Наконец мы дошли до самого важного, и основного в деле создания мода — писанины!
Помните, мы создали второй файлик, который называется так же как и ваш мод?
Открывайте его. Первые две строки копируйте из materials. Те, что с init.
Через строку, без четырёх пробелов или одного Tab, пишем:
label название_лейбла:
Название этого лейбла должно совпадать с тем, что вы писали под init.
Я же для наглядности написал test_mod_start, а не test_mod, как писал под init.
Основа БЛ это текст автора и чья-то речь, верно? Смотрим как их писать.
Весь текст пишется с 4-мя пробелами в начале, и под label. Не забываем об этом.
Чтобы написать текст автора, то есть просто текст, пишем кавычки, и в них текст:
Чтобы писать текст мыслей (с тильдами по бокам текста), перед кавычками добавляем инициалы th:
Именно эти инициалы мы прописывали для своих персонажей, и именно они используются для речи всех персонажей.
Чтобы написать речь кого-то, пишем его инициалы спереди кавычек, так же как и с мыслями:
тэг_персонажа “текст_кого_то“
У вас должно получится примерно вот так:
Большая часть оригинальных инициал персонажей из БЛ расписаны на этой знаменитой картинке:
Помимо этих, ещё имеются инициалы, собственно Семёна, и большинства героев, с условием неизвестности:
me — Семён
mep — Парень
unp — Пионерка (Лена)
dvp — Пионерка (Алиса)
usp — Пионерка (Ульяна)
slp — Пионерка (Славя)
mip — Пионерка (Мику)
uvp — Странная девочка (Юля)
elp — Пионер (Электроник)
shp — Пионер (Шурик)
mzp — Пионерка (Женя)
mtp — Вожатая (Ольга Дмитревна)
csp — Медсестра (Виола)
Визуальная составляющая
Сейчас ваш мод — просто резко появляющийся текст на чёрном экране с зимним интерфейсом.
Мы разобрались с речевой частью, пора разобраться и с визуальной! Затем займёмся и украшением текста.
Не забываем про 4 пробела, они пишутся всегда. Исключения только init и label.
- В игре существует 4 вида интерфейса — зимний, дневной, вечерний, ночной.
Последние три — летние. Думаю для чего они нужны и так понятно.
Вы же не хотите показывать, как ГГ загорает на пляже с зимним интерфейсом?
Чтобы изменить интерфейс, в тексте пишем одну из этих команд:
-
$ prolog_time()
Для зимнего.
-
Интерфейс можно плавно скрыть или показать. Чтобы это сделать, пишем в тексте:
- hide название_картинки_или_фона
Чтобы скрыть картинку или фон. А вы что ожидали? - show название_картинки with dissolve
Чтобы картинка появилась плавно. Растворение средней скорости. - dspr — самое быстрое растворение, эффективно при смене эмоций на спрайтах.
- dissolve2 — растворение, дольше dissolve.
- dissolve_fast — растворение, быстрее dissolve, но медленней dspr.
- hell_dissolve — очень долгое растворение, 50 секунд.
- dissolve_long — невероятно долгое растворение, 100 секунд.
- flash — белая вспышка.
- flash_red — красная (кровавая) вспышка.
- fade — затемнение.
-
Как аналог, можно использовать схему:
-
punch работает и с текстом. Чтобы текст появился с тряской, пишите так:
Показ спрайтов
Теперь мы видим площадь. Но мы не видим Алису! Покажем же её.
Не забываем про 4 пробела, они пишутся всегда. Исключения только init и label.
Дабы показать Алису, нужно вывести на экран её спрайт.
У каждого спрайта в названии есть инициалы владельца и эмоция. Есть ещё одежда и дальность, но для пользовательских спрайтов, порой хватает и первых двух. Так что спрайты вызываются также как и картинки с фонами, но в отличие от них, у спрайтов не слитное название параметров. То есть, не — show тэг_персонажа эмоция_и_другие_значения, а — show тэг_персонажа эмоция другие_значения.
Поэтому показываем спрайт примерно так:Чтобы показать спрайт на определённой позиции, у нас есть команда — at. Она пишется перед with. Выходит это:
show тэг_персонажа эмоция другие_значения at сторона_экрана with эффект
Вот возможные стороны:
- fleft — дальнее лево.
- left — лево.
- cleft — ближнее лево.
- center — центр. Используется только при перемещении спрайта с другой позиции в центр.
- cright — ближнее право.
- right — право.
- fright — дальнее право.
Получается, что мы вызываем второй, или любой другой по численности, спрайт подобной командой:
А если же мы хотим показать их одновременно, и при этом плавно, то делаем такой же фокус, который использовали с эффектом punch:
Однажды, в какую-нибудь тёмную ночь, вы заметите, что ваши спрайты слишком яркие. В этом случае вам поможет команды:
- $ persistent.sprite_time = ‘day‘ — для дневного освещения. Освещение по умолчанию.
- $ persistent.sprite_time = ‘sunset‘ — для вечернего освещения.
- $ persistent.sprite_time = ‘night‘ — для ночного освещения.
На первый взгляд, изменится не очень многое, но, поверьте, это очень полезная функция. Если вы прописали свои спрайты по специальному коду, то они тоже будут менять своё освещение, как и стандартные.
Где достать коды всех спрайтов смотрите в разделе Все необходимые коды.
linear, pos — Фокус с перемещением
Когда-нибудь вы можете захотеть плавно переместить спрайт, или любую другую картинку, на другой край экрана. Для этого есть команда — linear.
4 пробела помним?
Чтобы переместить изображение по горизонтали пишем такую схемку:
Первая строчка нам знакома, а вот вторая нет.
Обратите внимание, что вторая строка пишется после двоеточия, и на 4 пробела дальше.linear означает перемещение картинки, после чего пишется время в секундах, за которое она должна переместиться.
xalign и yalign определяют куда будет перемещаться изображение, по Y или по X. Y для вертикали, X для горизонтали.
Затем пишется сами координаты в формате 0.0 — 1.0, где 0.0 левый край экрана, а 1.0 правый. Писать обязательно с десятыми.Примечание: по неизвестным для меня причинам, перемещение по Y в Бесконечном Лете не работает, в отличие от других игр на движке Ren’Py. Вероятно тут виновата ошибка разработчиков, которые писали код игры. Но этого, как говорится, мы никогда не узнаем.
Для примера, перед тем как перемещать спрайт, нам нужно его плавно показать, иначе он появится в движении:
Из этого кода мы видим, что по центру экрана появится весёлая Алиса, а затем переместится к левому краю экрана.
Если писать координаты больше 1.0 или меньше 0.0 (например: -0.5), то изображение уйдёт за экран. Это можно использовать.
——————————————————————————————————-
Если вы захотели поставить картинку в какое-то определённое место, вам поможет команда — pos:Координаты расчитываются по пикселям стандартного разрешения экрана, а это — 1920×1080. Однако расчёт идёт не с привычного левого верхнего угла, а с левого нижнего. То есть левый верхний угол будет равен — 0, 1080.
Аудио
Казалось бы — у нас всё есть: фон, текст, спрайты. Но зайдя в мод, мы тут же заметим…
Что здесь гробовая тишина! Исправим это недоразумение!Не забываем про 4 пробела, они пишутся всегда. Исключения только init и label.
Как вы могли понять ранее, из курса по материалам, у нас есть три вида аудио — звуки, музыка и эмбиент. Чтобы их включить, у нас есть команда — play, и четыре дорожки воспроизведения:
- play musicназвание_музыки — для музыки.
- play soundназвание_звука — для звука. Воспроизводится лишь раз.
- play sound_loopназвание_непрекращающегося_звука — для непрекращающегося звука. Работает как дорожки music или ambience.
- play ambienceназвание_эмбиента — для эмбиента. Это звуки на заднем фоне — птицы, шум волн…
В БЛ музыка имеет весьма странную форму записи — music_list[“название_музыки”]. Из-за чего можно запутаться, и подумать, что music писать уже не надо. Но это не так. Код воспроизведения оригинальной музыки должен быть примерно такой:
Так как music это ID дорожки аудио, а music_list[“”] — это часть названия. Для своей музыки вы можете писать как адекватные люди, без этой тавтологии.
——————————————————————————————————-
Кроме того, что мы изучили выше, мы можем поставить аудио в очередь, командой — queue. Оно будет писатся вместо play:- queue sound название_звука
- queue sound название_следующего_звука
Работает только в пределах одной дорожки. То есть у каждой дорожки своя очередь.
Таким образом, у нас проиграет звук, а затем тут же пойдёт другой. Без необходимости высчитывать, сколько ему необходимо времени, и ставить на это время паузы.
Кстати, я не уверен что есть смысл в этой команде в любых других дорожках, кроме sound. Ведь там аудио проигрывается бесконечно. Как и лето.
——————————————————————————————————-
Когда же мы достаточно наслушаемся, останавливаем аудио командой — stop, с соответствующим ID дорожки:- stop music
- stop sound
- stop sound_loop
- stop ambience
- play music название_музыкиfadein сколько_секунд
- stop ambience fadeout сколько_секунд
fadein для плавного появления, а fadeout для исчезания. После них пишется сколько будет длиться эффект в секундах. Например:
Где найти все коды музыки, звуков и эмбиентов смотрите в разделе Все необходимые коды.
Пауза
Всем рано или поздно нужно сделать паузу. И мы не исключение. Думаю не стоит пускаться в объяснения по поводу паузы. Надеюсь все и так понимают зачем она нужна.
Не забываем про 4 пробела, они пишутся всегда. Исключения только init и label.
Чтобы сделать паузу используем одну из команд:
-
pause сколько_секунд — простая пауза.
Можно пропустить, нажав на Enter/Пробел/ЛКМ/Ctrl. Допустимо писать секунды в скобках. Но если подумать… Зачем заморачиваться?Секунды можно писать в десятых, то есть так: 0.2, 1.6, 32.4…
Примечание: если поставить паузу без секунд, не важно простую или сложную — игра остановится и продолжить можно будет, только нажав на Enter/Пробел/ЛКМ/Ctrl.
Так что не рекомендуется этого делать. А то у читателей может возникнуть затык, и они подумают, что игра зависла.Паузы рекомендуется ставить только со скрытым интерфейсом.
Знаете, пять секунд смотреть на пустую строку текста не очень-то интересно!Паузы — это очень важная часть визуальной новеллы. Не забывайте о них. Но и не делайте слишком много, и слишком долгие. Читатели не привыкли ждать!
Форматирование текста
Порой, нужно сделать текст необычным. Для такого случая существуют команды, которые пишутся прямо в тексте, внутри кавычек. Рассмотрим же их.
Не забываем про 4 пробела, они пишутся всегда. Исключения только init и label.
Сами коды в игре не видны, виден только эффект:
- — “какой_то_текст” — для курсива.
- — “какой_то_текст” — для жирноты.
- — “
какой_то_текст” — для зачёркивания. - — “какой_то_текст. другой_текст” — для паузы в отображении текста. Отображение сначала остановится, на том месте где стоит команда, а после нажатия на Enter/Пробел/ЛКМ/Ctrl продолжится, и закончится там, где либо стоит ещё одна пауза, либо где конец кавычек.
- n —”какой_то_текст. nдругой_текст” — для переноса остальной части текста на строку ниже.
- “ — “какой_то_текст_“что_то_в_кавычках“_продолжение_текста” — для того чтобы была возможность поставить кавычки внутри текста.
Уделите особое внимание пробелу, он нужен лишь один, так как команды исчезают из отображаемого текста.
Другие полезности
Вы хотите моргнуть? А может ваши глаза устали от всего этого, и вы хотите их закрыть?
Это можно устроить.
Пишем так:-
show blinking
Чтобы моргнуть.Для лучшего эффекта отделяем паузами, примерно так:
Вы хотите нам показать какой-то крутой видос? Без проблем!
Чтобы сделать это пишем прямо в блоке label:- $ renpy.movie_cutscene (“путь_к_видео”)
Полная команда будет примерно такая:
За вами погоня? Или может это вы за кем-то бежите?
Чтобы все поняли что вы бежите, вам поможет данная комбинация:Как вы поняли — это показ фона с эффектом. Так что, чтобы выключить бег просто снова включите этот же фон, ну или другой, без этого эффекта.
Проверяем, что получилось
Мы уже сделали достаточно, чтобы было на что посмотреть. Думаю каждому захочется проверить, что же он там наделал.
Для этого запускаем игру > переходим в настройки (инструменты) > моды и пользовательские сценарии > и в данном списке выбираете ваш мод.
Если вы сделали всё как надо, он там появится.
А также, после того как вы запустите впервые ваш мод, в папке мода появится копии ваших .rpy файлов, но с расширением .rpyc. Это закодированные файлы текста, и именно их использует игра. Так что если удалить файлы .rpy, игра спокойно загрузит ваш мод.
Глава 3: menu — Сложности выбора
По сути, сейчас вы уже научились всему, что может понадобится при создании мода. Но только в случае, если там не будет выборов и если там всего одна концовка. Если же вы решите, что кинетическая новелла — это не про Вас, то смотрите самый сложный раздел руководства — выборы и их последствия.
===========================================================================Чтобы предоставить читателю выбор, пишем такую систему команд:
Команда menu: вызывает меню выбора. Перед ним, желательно скрыть интерфейс.
Затем, на следующей строке мы делаем 8 пробелов, так как формируется блок в блоке. Чем больше блоков, тем больше пробелов. Их количество всегда увеличивается на 4.
После этих 8-ми пробелов в кавычках пишется выбор так, как он будет отображаться в игре, и двоеточие, означающее формирование ещё одного блока.
Ниже, после 12-и пробелов будут последствия выбора. Это не обязательно должен быть текст, однако там должна быть хотя бы одна команда, иначе движок будет жаловаться, что блок пустой и не запустит нам игру.Выбор не обязательно должен быть из двух или более вариантов, их количество не ограничено. Ведь выбор из одного варианта — тоже выбор.
Чтобы закончить последствия выбора, просто пишем дальше с 4-мя пробелами, как и раньше.
Если хотите сделать выбор без исчезания текста, то есть, чтобы он отображался внизу, как и до выбора, то пишите так:
А если вы в режиме NVL (тескст поверх экрана), и хотите чтобы выбор был там, перед выбором пишите команду define menu = nvl_menu, как на примере ниже:
if, else — Снова переменные
При условии, что вы прописали изначальные значения переменных ранее, их значение можно будет изменить в процессе игры. Конечно же для этого пригодятся выборы, иначе — какой смысл их писать вообще?
Я надеюсь вы не забыли про 4 пробела?)
Чтобы изменить значение переменной с True на False или наоборот, а также чтобы изменить числительное значение на конкретно другую цифру пишем так:
- $ название_переменной = значение
У вас зоркий глаз, если Вы заметили, что это точно такой же код, который мы писали в materials. Различие лишь в том, что прописывать переменные изначально нужно в блоке init, а изменять значение в label. Иначе не работает, естественно.
А вот если вам приспичит прибавить или отбавить какое-то число к/у текущему/его количеству/а, пишем более интересные команды:
-
$ название_переменной+=сколько_добавить
Чтобы добавить сколько-то очков к значению.Логично, что изменять переменные нужно в зависимости от выбора читателя. Так что пишем эти команды в блоке последствий выбора.
===========================================================================Когда пришло время проверить сколько очков отношений у читателя с персонажем NN, или съел ли он всё таки свой суп, пишем проверку переменных.
Проверки бывают трёх видов — равно, больше, меньше. С True или False больше и меньше не работает. Как ни жаль.
Для проверки используется команда — if, за ним пишется название переменной, дальше в качестве обозначения равенства пишется двойное равно — ==, а для обозначения больше или меньше используются соответствующие знаки — >, <.
Затем после двоеточия идут последствия, как и после выбора.
Последствия последствий выбора…-
if название_переменной==значение:
Если значение должно быть равнотакому-то.Всё естественно в системе блоков:
В данном примере некая Она, при достаточных очках любви, одаривает главного героя улыбкой, однако это никак не влияет на его последующий выбор.
Соответственно, если очков любви недостаточно, то Она даже не посмотрит на нашего героя, но выбор появится, и в итоге это никак не помешает ему потанцевать с Ней.
Без else или jump большего не сделать.
——————————————————————————————————-В случае когда нам нужно сделать, по типу — “либо так, либо иначе“, используем команду — else. Ведь, если мы не будем использовать эту команду, история продолжится так, как будто ничего не произошло. Как альтернативу, можно использовать jump, но об этом позже.
else пишется на том же уровне что и if, то есть либо на 4-х пробелах, либо на 8-и и выше.Думаю хватит и примера, чтобы вы поняли зачем нужна эта команда:
Тут показаны только текст и проверка переменных, но для понятия сути, думаю вам хватит. =)
(Пример придуман моей бурной фантазией по ходу написания раздела. Ни в одном из моих, или мне известных, модах такой сцены нет. Так что вам ничего не мешает использовать её, вероятно отредактированную, в своём моде. Или же сделать что-то по такой же схеме)
——————————————————————————————————-Ходят слухи, мол, ещё есть какой-то — elif, который может использоваться между if и else, однако у меня ничего с этой командой не получилось сделать. Игра просто делала вид, будто её не существует. Но и не жаловалась, что доказывает, что движок знает эту команду.
Если вы лучше знакомы с Phyton или с самим Ren’Py, думаю вы сможете разобраться с этой командой.
——————————————————————————————————-Когда последствия проверки переменных закончатся, возвращаемся с 8-и пробелов к привычным 4-м.
С помощью тех же переменных последствия ранних решений могут проявится где-то ещё, и не раз. Собственно, всё это видно из примера выше.
jump — Зайчик делает прыг-прыг
В случаях когда вы разделили мод на несколько частей, и каждая из них в отдельном файле, или же когда после выбора читатель должен отправиться совсем другой дорогой, вам поможет простая команда — jump. Она позволяет, буквально, прыгать между лейблами.
Пишется таким образом:- jumpназвание_лейбла
Таким образом у нас получилось две разные ветки событий. Чтобы не писать это всё в последствиях выбора, так как там может быть очень много, мы вывели это в отдельные лейблы, которые вполне могут быть, даже, в отдельном файле.
——————————————————————————————————-Помимо jump у нас имеется ещё одна подобная команда — call. Она перемещает читателя на другой лейбл, как и jump, но после его окончания возвращает туда, откуда было совершено перемещение. Это можно использовать, например, для длительных флешбэков:
Как вы видите, call пишется точно также как и jump, но в отличие от него, call не является окончанием блока или лейбла.
Карта
Мы могли забыть о такой прекрасной вещи как — карта. В БЛ есть возможность выбирать куда пойти по карте. Смотрим что для этого нужно.
Чтобы показать карту пишем команду:
- $ show_map()
Но так карта будет пустая, и с ней нельзя будет взаимодействовать. Смотрим дальше.
Чтобы добавить локацию пишем код по такой схеме:- $ set_zone(“название_локации“, “название_лейбла“)
Пишем эту команду столько раз, сколько будет локаций. У каждой должен быть свой лейбл. При нажатии читателем на эту локацию его перенесёт на соответствующий лейбл. Так что нет нужды писать jump.
При повторном показе карты выбор локаций останется. Чтобы этого избежать пишем такую команду:
- $ disable_all_zones()
Чтобы сделать возможность идти только туда, куда ты ещё не ходил, то есть чтобы можно было обойти все локации, но только один раз, используем переменные и их проверку.
Дарую вам примерную схемку:Не самая удобная, но вполне рабочая. В данном примере три локации: лес, музыкальных клуб и пляж. Всё пишется в отдельном лейбле, чтобы можно было вернуться с лейблов локаций обратно на карту. В начале пишется отключение активных локаций (иначе всё схема насмарку), и проверка, не обошёл ли читатель всё. Если нет, показывается карта, и те локации в которых он не был. Если же он всё обошёл, то его переносит на следующий за этим разделом лейбл.
Естественно, чтобы вы смогли её использовать, Вам будет нужно поменять все названия лейблов и переменных на нужные Вам. Хотя вы можете использовать и мои)
Главное не забудьте их прописать в materials.Где достать все коды локаций смотрите в разделе Все необходимые коды.
return — Конец всему
Вот и пришло время прощаться…
Когда в конце последствий выбора должен быть конец игры, пишем команду — return.
Если текст в лейбле закончится, эффект будет тот же.Это самая ужасная, страшная, и жестокая команда в этой игре, но каждый мододел однажды её напишет.
save_name — Сохранения
Ошибка большинства моддеров — отсутствие названия мода в сохранении. То есть ты сохраняешь игру, проходя мод, а потом не можешь понять, что это вообще за сохранение такое! Эта ошибка к сожалению появляется даже у опытных мододелов, хотя исправляется она элементарно.
4 пробела, 4 пробела, помним мы о них всегда!
Так как мы уже сделали большую часть мода, распределить сохранения будет проще. Чтобы добавить сохранению название, в блоке label пишем такую команду:
- $ save_name = (‘название_сохранения‘)
Просто, неправда ли? В то место, где название_сохранения, пишем как раз название сохранения. Если получается слишком длинное, какую-то часть можно перенести на другую строчку с помощью — n, иначе оно будет вылазить из слота. Например:
Это название будет отображаться в игре так:
Тестовый мод. День 1
Прибытие в лагерь- $ new_chapter(день, u”Название_сохранения”)
Получается примерно так:
Сколько всего дней есть на этих мониторах, я, честно говоря, не помню, но где-то 5 — 7.
Все необходимые коды
Давным-давно, много лет назад, на просторах интернета я нашёл несколько файликов, в которых оказались расписаны коды всех локаций карт, BG, CG, музыки, звуков, эмбиента и спрайтов. Честно, я не знаю кто этот святой человек, что написал всё это, но я выражаю ему огромную благодарность.
Так что у меня был выбор, между написанием отдельного руководства, где представлены только эти коды (так как их, ну о-о-очень много), и закидыванием этих файликов в один архив.
Я выбрал второе.
К тому же там моё Полевое руководство, по которому я и писал Это руководство.В общем. Я загрузил этот архив на Яндекс Диск, и теперь вы все сможете его скачать. Там будут оригинальные (почти) файлики со всеми кодами того-сего, а также моя Мини-справка, где есть всё что и в этом руководстве, но в сильно укороченом виде.
Она выглядит вот так:
Не обращайте внимания на что-бы… Это уже давно в прошлом…
Ещё, для пользователей Notepad++, я оставил подарочек в виде 3-х синтаксисов:
- sprite_sintдля сворачивания всех спрайтов определённого персонажа в файлике про спрайты.
- spravka_sintдля красивого и сворачивающегося текста в Мини-справке.
- И самый важный — renpy_sint, который даст вам возможность видеть код мода также как и я, и как он был показан на скринах выше.
Пример:
Все эти синтаксисы сделаны мной, и вы их спокойно можете изменить, если захочется.
(Для тех кто будет использовать renpy_sint: при добавлении ваших новых персонажей в мод, вам будет нужно его добавить и в синтаксис, в 1-ю группу, в разделе Ключевых слов.)Чтобы скачать этот архив, просто нажмите на словосочетание скачать архив ниже.
Скачать архив [disk.yandex.ru]
Не бойтесь скачивать его, ничего такого там нет.Все коды подписаны на русском, так что вам будет достаточно скопировать нужный код из файлика и вставить в мод. Я сам ими постоянно пользуюсь)
Публикуем и обновляем детище
Время финального этапа — публикации мода.
Обратите внимание — мы выкладываем не ту папку, которая в папке mods, а отдельную папку, что с публичной версией.
Итак. Вот что мы делаем, для того чтобы выложить наш мод:
1. Копируем папку мода куда-нибудь, например в Everlasting Summergame. Главное не оставлять её в mods.
2. В путях файлов в materials убираем — mods/название_мода/. Это можно сделать разом, с помощью замены текста в Notepad++, как показано на скриншоте ниже.
Не забудьте про это!
2.1. При желании скрыть от хитрых читателей, которые знают как делается мод, ваш исходный код удаляем файлы с расширением .rpy, и оставляем только .rpyc.
.rpyc должен был появится после запуска игры с модом.3. Когда мы полностью подготовили мод к публикации, запускаем от имени администратора ES_Content_Uploader, что находится в папке mods.
Нас встретят такой вот приветственной надписью:4. Жмём Создать новый предмет.
5. Вам будет представлен ID вашего будущего мода. Запишите его куда-нибудь. Затем жмём Продолжить.
6. Появится весьма интересное окно:
Многим тут уже будет всё интуитивно понятно, но мы всё же разберём всё по пунктам.
6.1. Пишем название мода в строке Название предмета.
6.2. Затем, в Описание предмета можем написать первое описание. Но это не обязательно. Вы можете написать его позже, уже на странице мода в мастерской.
6.3. Указываем путь к папке мода, нажав на Обзор…, после чего появится новое окно. Там мы заходим в папку мода, и в ней нажимаем на кнопку Выбор папки в правом нижнем углу окна.
6.4. Если у вас уже готов логотип мода, то нажимаем на Обзор… у строки Обложка предмета, в новом окне просто выбираем наш логотип. С ним может быть много проблем, так что возможно придётся перепробовать множество расширений, разрешений и соотношений сторон картинки… Но в итоге вы сможете его добавить.
6.5. И у нас осталась, опять же, необязательная строка с описанием обновления. Его тоже можно написать в самой мастерской.
7. Когда всё заполним, нажимаем на Загрузить, после чего начнётся загрузка.
И в итоге нас обрадуют такой вот прекрасной надписью:
Которая будет означать, что ваш мод успешно выложен. Поздравляю!
Вы всегда сможете подписаться на свой же мод, и поиграть в него. Только не забудьте убрать папку мода, в которой вы работали, из mods. Иначе будет капут.
Мод-то мы выложили, а обновлять кто будет? Тоже мы.
Смотрим как.1. Делаем необходимые изменения в моде, и снова копируем их всех в нашу папку, с публичной версией мода.
2. Снова запускаем ES_Content_Uploader, но на этот раз нажимаем на Обновить существующий предмет.
3. Появится окно, которое потребует ID вашего мода. Вы же записали его, да?
Но если нет, то это не такая уж большая беда. Переходите на страницу вашего мода в мастерской, и в зелёной строке сверху копируйте цифры ID. Ну, если у вас там нету этой строки, то просто скопируйте адрес страницы, с помощью правой кнопки мыши, вставьте куда-нибудь, и оттуда вытащите ID.
Ну или можно подписаться на свой мод, а затем найти его по пути:
…Steamsteamappsworkshopcontent331470
Просто полазайте по папкам, и в одной из них будет знакомые вам файлы. Это и есть ваш мод)4. Как напишем ID в нужное поле, нажимаем продолжить, и появляется уже знакомое нам окно:
Однако в нём автоматически будут стоять галочки, запрещающие изменять название и описание предмета. Что ж, на неё всегда можно нажать снова, если вы захотите изменить то или иное.
Собственно тут всё как и раньше. Выбираем свою папку, логотип если надо, и пишем что изменилось, если хотите.
5. Нажимаем на загрузить, и пойдёт загрузка.
Затем нас снова поздравят той же самой надписью:
Послесловие
Вот и всё. Вы сделали свой собственный мод, уверен он будет отличным!
Посему я могу с гордостью сказать:Спасибо всем, кто читал и пользовался моим руководством, всем кто оценивал, выдавал награды, комментировал и добавлял в избранное, как во время разработки, так и уже после!
А ещё я хочу сказать спасибо тем замечательным людям, которые своими руководствами, обучили меня всему, чему теперь я обучил вас!
Вот эти руководства:Руководство закончено, но конечно же может быть дополнено в будущем.
Если что-то не получается, не стесняйтесь спрашивать.
Постараюсь помочь, всем чем смогу!Лето, Советы и (не)много кода

mods[«»] — команда, которая добавляет мод в список модов. В кавычках необходимо указать блок (латиницей), на который игрок переходит во время запуска.
= — присваивание блоку запуска определённое имя в списке модов.
u — в строке используются символы Unicode. И в кавычках — название мода на любом языке.Чтобы наш мод шёл плавно и без проблем, необходимо, чтобы из каждого блока можно было попасть в следующий. Для кинетических модов (моды, которые не имеют выбора и движутся по одной сюжетной линии) вообще не обязательно иметь более одного блока, но можно использовать несколько для красоты.
После этого урока ты уже сможешь написать кинетический мод со встроенными материалами.
Создаём наш запускаемый блок:
После метки идёт её имя — то самое, которое мы задали в списке модов.
И не забудь про «:»! Это показывает, что ниже — содержимое этого блока.Едем дальше. Теперь ты можешь писать любой текст, включать любую музыку и вставлять любые картинки. Как? Очень просто!

Выглядеть это будет так:

Теперь — сам код.
play — запускает звук
music — помещает его на канал «музыка». Есть три канала: music, sound и ambience. Music и ambience проигрывают звук в цикле.
music_list[«»] — звук берётся из списка самой игры.
fadein <число> — нарастание музыки в течение указанного количества секунд. Необязательно.scene — задаётся самый нижний слой, на который чаще всего помещаются фоны. При применении этой команды на непустой экран все спрайты и картинки скрываются.
bg — указывает на то, что картинка является фоном. Можно использовать и без bg, но не всегда картинки будут работать.
ext_camp_entrance_day — название картинки.
with dissolve — анимация появления картинки. Можно использовать вообще без анимации, но это будет не так красиво. Dissolve — медленный переход, dspr — быстрый и используется чаще для изменения эмоций. Также существуют и другие, но об этом позже.show — появление картинки на фоне
sl — название спрайта персонажа
nomal — эмоция персонажа
pioneer — одежда
far, close — существует три положения относительно игрока. По умолчанию это среднее положение. Кроме этого, есть far — дальнее и close — ближнее положение.
at left — положение относительно центра экрана. Слева направо: fleft, left, cleft, center, cright, right, fright. Если персонаж уже находится в нужном положении, можно не использовать.
Также можно использовать только один wih dissolve на следующей строке после описания Слави. Тогда фон и спрайт появятся одновременно, а не последовательно. Также это можно использовать для одновременной смены эмоций разных персонажей.Весь текст пишется в кавычках.
— пауза во время чтения. То есть, игрок должен нажать ЛКМ ещё раз, чтобы перейти к следующей части.
sl, me — имена персонажей, отображаются в верхней части текстового окна. Полный список — тута. Кроме того, тут списки всех материалов из игры.
th — мысли (текст такого типа
)
И return — возврат на предыдущий уровень. Если уровень последний, то игра выйдет в меню.Комментарии в коде можно оставлять с помощью #. Движок игры пропускает всё, что написано после этого символа и сразу переходит на следующую.
На этом первый урок закончен. Потренируйся с этими инструментами, а если захочешь поделиться результатами — шли файл с кодом в комментарии с меткой «Урок 1».
Ты уже достаточно потренировался с линейным моддингом, но хочется чего-то большего?
Добро пожаловать во второй урок!Но до этого надо исправить парочку недочётов: остановим музыку.

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

После указания персонажа, эмоции и типа одежды указываем, за кем должен стоять персонаж. В данном случае на экране у нас только Славя, поэтому пишем behind sl. Если ты используешь far или close, то команда behind должна стоять после. Но обязательно перед with-командой (или at, если она есть).
Как сделать мод на бесконечное лето
Данная статья была написана мной более года назад в качестве отчёта о практике для универа. В кои-то веки я решил её опубликовать. Надеюсь, ещё не совсем потеряла актуальности :/
В связи со спецификой появления, думаю, во избежание лишних вопросов мне стоит пояснить, что САФУ/NArFU — это название университета, а ИСМАРТ — конкретный институт в его составе, где я учусь. Стиль изложения также может несколько отличаться от моих обычных публикаций, так как подразумевалось, что читать текст будут люди совсем далёкие от игр и современной сетевой культуры.
Также для основной версии сайта я прикрутил подсветку синтаксиса (на lite- и pda-версиях не работает), но Ren'Py — довольно специфичный язык, поэтому используется подсветка от Python'а. В итоге подсвечены будут, по сути, только строки и некоторые совпадающие ключевые слова.
Если при чтении возникнут какие-то проблемы или вопросы по коду, то можно скачать архив с примерами. Он упакован в формат 7z, потому что, в отличие от zip’а, тот умеет упаковывать идентичные файлы так, чтобы они занимали место, как один.
Гайд по созданию визуальной новеллы
Здравствуй, дорогой читатель! Возможно, ты уже слышал о такой широко известной в узких кругах видеоигре от отечественных разработчиков, как «Бесконечное лето» (Everlasting Summer)? Впрочем, если нет, то ничего страшного: я расскажу о ней вкратце.
Как гласит официальный сайт, «„Бесконечное лето“ — это визуальная новелла от российских разработчиков, дарящая самые искренние и светлые переживания об ушедших днях и надеждах, которым ещё предстоит сбыться». Поясняю:
- Визуальный роман (но чаще встречается вариант с англицизмом: визуальная новелла) — это жанр компьютерных игр, в котором упор делается на текстовый контент, сдобренный порциями аудиовизуального сопровождения. По сути, это скорее книги, чем игры, но обильно снабжённые иллюстрациями, анимацией, музыкой и звуками окружающего мира. Также, в отличие от книг, представители данного жанра обычно имеют нелинейный сюжет с несколькими концовками, и исход зависит от выборов игрока.
- «Бесконечное лето» повествует историю об одном асоциальном человеке, волею судеб оказавшемся в загадочном пионерлагере. Многим игра нравится именно атмосферой, позволяющей почувствовать себя пионером либо поностальгировать о временах былой молодости.
Однако мы здесь собрались вовсе не для того, чтобы слушать рекламу и хвалебные оды, не так ли? Так что перейдём ближе к сути.
«Бесконечное лето» написано на бесплатном движке Ren'Py. Это специальный движок, предназначенный для создания визуальных романов сценаристами, далёкими от программирования. Он имеет предельно простой синтаксис и множество встроенных средств для реализации практически всех функций, которые могут понадобиться в подобных играх. Тем не менее, сам движок свободен (open source) и расширяем, предоставляя возможность пользоваться всей мощью языка Python, на котором он написан.
В этом небольшом гайде мы рассмотрим базовые возможности Ren'Py, а также слегка коснёмся темы создания модификаций к игре «Бесконечное лето».
Для того, чтобы начать создавать игры на Ren'Py, первым делом скачай и установи/распакуй набор для разработчиков с официального сайта. После запуска покажется такое окно:

Это Ren'Py Launcher — программа, из которой можно запустить любой из разрабатываемых проектов, открыть папку с ним или сразу перейти к редактированию скриптов. Все команды написаны на простом английском языке, не выходящем за рамки даже слабой школьной российской программы, так что не вижу смысла на них останавливаться. К тому же в настройках можно включить кривой перевод на русский язык.
Создай новый проект, укажи папку (желательно, без кириллицы, но это не обязательно), имя проекта (вот тут только латиница!) и выбери любую тему (это непринципиально).
Ren'Py уже при создании производит базовую настройку проекта, предоставляя интерфейс для меню, стили по умолчанию и т. д. Можешь посмотреть файлы скриптов, которые он создал:
- В options.rpy находится большинство настроек: размеры окна, стили, переходы по умолчанию и т. д.
- В screens.rpy описываются меню, диалоговое окно и прочие «экраны».
- script.rpy предназначен, собственно, для самого скрипта-сценария романа.
Вообще, это всё условно. Все файлы проекта находятся в папке game и Ren'Py читает там все файлы с расширением *.rpy, так что можно разбивать скрипты на любое количество файлов.
Я бы мог рассказать ещё про основы языка Python, как сделано в документации, но всё, что нам понадобится для базового знакомства, интуитивно-понятно или будет пояснено в месте применения. Так что предлагаю просто нажать по ссылке на scripts.rpy в «лончере» (launcher), выбрать редактор (любой, я вообще пользуюсь Sublime Text 3 с плагином) и приступим к созданию твоего первого творения на Ren'Py!
Текст, картинки, переходы
Сотри всё, что уже есть в файле: мы начнём с нуля.
Для упорядочивания кода Ren'Py пользуется системой меток (привет, ассемблер и GOTO!). При выборе кнопки «Начать игру» в главном меню игры, которое отображается сразу после запуска, управление передаётся на метку start:
Что мы видим? После объявления метки start начинается принадлежащий ей блок кода, строки которого обладают отступом в 4 пробела. Внутри блока расположены речевые конструкции (say statements), с помощью которых выводится текст.
В первой и третьей строчках (блока) располагаются слова автора или рассказчика. Фраза просто заключается в двойные кавычки (если внутри фразы нужно вывести кавычки, то они предваряются обратным слешем: \").
Во второй и четвёртой строках находится фраза персонажа под именем Аня. Видно, что имя персонажа, так же заключённое в двойные кавычки, и его фраза отделяются пробелом.
Возникает первая проблема: постоянно приходится повторять имя персонажа (а в больших сценариях с более длинными именами это реально представляет проблему). Ну и сразу обращаю внимание на вторую: все персонажи отображаются абсолютно одинаково, без какой-либо толики индивидуальности. Решим обе эти проблемы:
В самое начало я добавил новую строку, которая определяет (define) нового персонажа (character) и задаёт ему имя и красноватый цвет имени (color). Новый персонаж присваивается короткой переменной a, которая теперь используется в речевых конструкциях вместо имени. Обратите внимание, что определения (что персонажей, что изображений, как мы увидим позже) пишутся вне любых меток, так как выполняются во время инициализации (немного про это будет сказано позже).
Что же у нас получилось?

Хм, надо бы избавиться от этих шашечек и добавить собственный фон. Я использую, например, фотографию крыльца своего института, найденную в Интернете. Закинь любое изображение достаточного размера в папку images внутри папки game. Внутри этой папки Ren'Py сканирует все изображения и по определённым правилам создаёт для них имена, но для наглядности мы определим фон вручную. Самый простой способ:
image bg ismart = ‘images/ismart.jpg’
Просто путь к файлу! Но если мы сделаем так, то получим странную картину:

Виной всему слишком большой размер изображения. Поэтому придётся немного усложнить определение. Вот весь код:
Во! Теперь всё в порядке:

Теперь объясню, что делает добавленный код и как вообще происходит отображение. Всего появились две новые строчки: конструкция с image и конструкция с scene:
- image, собственно, определяет изображение. Между ключевым словом и знаком равенства помещается имя отображаемого объекта. С ним не всё так просто. Как мы увидим дальше, в играх такого жанра, часто используются так называемые спрайты, то есть изображения персонажей с разными эмоциями и одеждой. Соответственно, частой операцией является смена спрайтов одного персонажа. По этой причине название изображения для Ren'Py состоит из, собственно, имени и атрибутов, разделённых пробелами. Всё это станет понятнее, когда будем рассматривать спрайты. А сейчас достаточно понять, что bg — название изображения, ismart — атрибут.
- scene, как понятно из названия, предназначен для смены сцены. Выражение с этим словом очищает экран от любых других изображений и выводит указанное (обычно фон, хотя может и не выводить ничего).
- im.Scale(d, width, height) — функция масштабирования, которая принимает отображаемый объект (displayable), в частности изображения, и изменяет его размеры к указанной ширине (width) и высоте (height). Сразу замечу, что существует аналогичная функция без префикса im.* (вне объекта im), которая отличается тем, что производит расчёты при каждом отображении и не сохраняет результат вычислений при определении.
- config.screen_width и config.screen_height — две переменные в объекте конфигурации, хранящие заданные в настройках ширину и высоту экрана игры (их легко можно найти в options.rpy).
Надеюсь, я объяснил достаточно понятно. Давай теперь поиграем со стилями? Открой screens.rpy, найди в самом начале описание экрана диалогов (screen say) и удалим всё «лишнее», добавив немного своего (выделено полужирным):
Рассмотрение стилей, к сожалению, выходит за рамки данного гайда, так что я не стану ничего пояснять. Будем считать, что разобраться в работе стилей будет твоим домашним заданием 😉
Ну а своим вандализмом мы добились такого цветастого безобразия без меню и возможности переключения режима отображения имени персонажа (в том же окне или в отдельном) из сценария:

Мы обязательно должны рассмотреть отображение спрайтов, изменение места их расположения и переходы, но искать спрайты в Интернете мне лень, так что рассмотрим этот материал внутри обещанного блока про создание модификаций для «Бесконечного лета».
Прежде всего скачай саму игру: либо через сервис цифровой дистрибуции Steam, либо через торрент-трекер Rutracker. Актуальные ссылки можно всегда найти на официальном сайте. Далее зайди в папку с игрой (для версии из Steam это \SteamApps\common\Everlasting Summer ). Там обычная структура файлов игры на движке Ren'Py. Заходим в game, как и прежде, а оттуда в папку mods. Скопируй туда scripts.rpy нашего проекта. Можешь даже его как-нибудь переименовать — не суть.
Теоретически можно создать наш файл со скриптом в любом месте внутри папки game, но давай будем придерживаться соглашений. К тому же, нам надо перекинуть и картинку. Создай папку narfu_images рядом с файлом скрипта и скопируй туда наш фон.
В последних сборках игры добавлен загрузчик модификаций, так что нам нужно лишь дать ему знать, что мы есть за скрипт. Открой файл в любимом текстовом редакторе. Пришло время познакомиться с блоками инициализации и запуском кода на Python!
Определение изображений и персонажей, как было сказано в примечании ранее, автоматически размещается в блоке инициализации, который выполняется до загрузки игры. Соответственно, это то самое место, где наш скрипт будет заявлять о себе. Добавь этот код в самое начало скрипта:
Блок инициализации объявляется ключевым словом init. Если дальше идут выражения на языке Python, а не на Ren'Py, то добавляется слово python. Вообще, в любом месте блоки кода на Python объявляются с помощью этого слова. Другой путь написать одиночную команду на Python — использовать знак доллара ($) в начале строки.
В примере выше я вместо слова python явно задал приоритет блока. Блоки выполняются от меньшего приоритета к большему. По умолчанию подразумевается блок с нулевым приоритетом. Порядок выполнения блоков с одинаковым приоритетом не гарантирован и может быть случайным.
Теперь объясняю саму команду. Переменная mods — это специальный список «ключ-значение», где перечисляются все модификации. Ключ должен быть уникальным значением на латинице без пробелов и в кавычках. Значение — название мода для отображения в загрузчике модификаций. Ключ играет роль названия метки при запуске мода, так что исправь label start на label narfu_practice. Также давай уберём определение персонажа a. Он нам больше не понадобится.
Теперь сделаем магию! Вставляй в редактор оставшийся код и запускай игру через меню модификаций в настройках!

С чего бы начать? «Бесконечное лето» предоставляет интерфейс, персонажей, спрайты к ним, фоны и музыку. Здесь мы пока использовали только первые три пункта.
dv — это персонаж и тег изображений для Алисы Двачевской. Соответственно, scared, raged и pioneer — это атрибуты. Вообще, названия всех спрайтов в игре строятся по следующему плану: короткое_имя_персонажа эмоция одежда . Полный список спрайтов можно найти в знаменитых уроках LolBot'а (один из программистов игры, создатель системы модификаций). Официальной ссылки, насколько мне известно, не существует, а прочие быстро станут не актуальны, так что Google в помощь!
При показе второго изображения с таким же тегом, первое исчезает. Это нужно как раз для удобной смены эмоций, как сделано в нашем примере. Чтобы отобразить два одинаковых изображения, можно воспользоваться конструкцией show..as <новая метка> (см. следующий параграф).
Для отображения спрайтов используется ключевое слово show, похожее на scene, но не очищающее экран. Для обеих конструкций могут быть указаны переходы с помощью конструкции with. Строго говоря, изображение вообще отображается только после этой конструкции. Таким образом можно планировать показ нескольких изображений, для которых потом задавать один переход. Если with не встречается до следующего диалога, то Ren'Py использует with None, просто выводящий изображения мгновенно. А ещё его полезно использовать, когда нужно одно изображение отобразить мгновенно, а лишь второе — с переходом.
Ren'Py имеет ряд встроенных переходов (мы использовали dissolve и fade), а также позволяет создавать свои с помощью специальных функций (например, with Dissolve(0.5) для «растворения» одного изображения в другом за полсекунды). Всё это очень интересно, но выходит за рамки данного гайда. Смотри документацию, если хочешь знать больше!
Обрати внимание, как отображаются диалоги с изображениями в обоих случаях речи Алисы: в первом сначала рисуется персонаж, а затем печатается текст, а во втором — и текст, и персонаж переключатся с «растворением» одновременно.
Для того, чтобы диалоговое окно не мерцало при показе изображений, я использовал window show, которое держит окно всегда на экране. По умолчанию же оно показывается при отображении диалогов и скрывается при показе изображений, что я обратно и включаю в конце скрипта (надо помнить, что мод заканчивается, но игра продолжает выполняться, и мы обязаны всё вернуть в исходное состояние!).
Разумеется, существуют конструкции hide для скрытия изображении и window hide для скрытия диалогового окна.
А теперь давайте добавим второго героя, музыки и украшательств!
Прочитал комментарии? Я не буду пояснять про особенности игры, так как статья не об этом. Здесь мы обратим внимание позиционирование изображений, стилизацию текста и музыку.
Для проигрывания музыки и звуков существуют play music и play sound соответственно. Они принимают либо путь к файлу, либо список путей к файлам (в данном случае все пути к музыке из игры расположены в специальном списке, из которого мы берём конкретный). Для остановки используются stop music и stop sound, соответственно.
Музыка и звуки воспроизводятся на разных каналах, громкость которых игрок может регулировать в меню по отдельности. Ну а ещё звуки выполняются один раз, а музыка зацикливается. Разработчик же может регулировать не только громкость, но и скорость воспроизведения, баланс в колонках и многое другое. В том числе, можно создавать свои собственные каналы и играть несколько звуков одновременно.
Расположение спрайтов задаётся при показе либо с помощью at, либо в виде отдельного блока. В первом случае указывается предопределённое расположение (left или right, например), а во втором используется специальный язык ATL. Подробнее о нём можно прочитать в документации, а я лишь опишу базовое позиционирование, о котором также можно посмотреть наглядно в туториале, прилагаемом к Ren'Py SDK.
Положение изображений по обеим координатам задаётся с помощью двух точек: одной на изображении, называемой якорем (anchor), и второй на экране (pos). Задаётся либо с помощью целого числа, обозначающего координаты относительно верхнего левого угла экрана, либо с помощью дробного числа от нуля до единицы, обозначающего долю экрана, как сделано в примере.
Стилизация текста. Текст может содержать специальные теги, показывающие, как он должен отображаться. Для знакомых с языком HTML тут будет совсем просто: чаще всего используются точно такие же теги: , , , (для ссылок). Хотя есть и различия:
. Просто. Также в тексте в квадратных скобках могут использоваться подстановки из переменных, определённых в коде. Если же есть необходимость использовать в тексте сами символы фигурных и квадратных скобках, но их нужно продублировать: <<, >>, [[, ]]. Внизу на картинке приведён результат. Неплохо получилось, не так ли?

За сим я, пожалуй, откланиваюсь. В Ren'Py есть ещё очень много всего интересного, но место в этой статье не резиновое. Дальше, дорогой читатель, можешь либо почитать документацию (если знаешь английский язык, конечно), либо искать обучающие видео и руководства от других людей.
# Первые шаги
Для начало нужно создать файл с расширением .rpy . Затем открыть его в текстовом редакторе, и следовать далее по руководству.
# Написание кода
Стиль и синтаксис Ren’Py похож на Python. Если знакомы с ним, то проблем возникнуть не должно.
Файлы состоят из блоков и команд в блоках, например:
Команды в блоках должны везде иметь одинаковый отступ. Будь то 2 или 4 пробела. В большинстве случаев рекомендуется использовать 4 пробела.
В редакторе кода будет по умолчанию выставлено значение отступов, поэтому рекомендуется использовать TAB для отступов.
Следует помнить, что Ren’Py не любит табуляцию, выкидывая ошибку (Traceback) при наличии подобного. Один из вариантов решения подобной проблемы: настройка авто-замены табов на пробелы в настройках Вашего рекдактора/с помощью установки соответствующего расширения.
# Объявление мода
Шаги, приведенные ниже крайне важны. Без них мод не будет виден в списке модов в игре.
Для того чтобы игра поняла, что файл (в котором строчки будут написаны) является модом, нужно написать следующее:
Разберем более детально пример выше:
- my_mod — название начального лейбла мода. При запуске мода, всегда первым начинает запускаться этот лейбл, указанный внутри командых скобок. Не будет виден пользователю. Должен быть уникальным, иначе возможны конфликты с модификациями, имеющими лейблы с таким же названием. Рекомендуется использовать только латиницу!
- Мой мод — название мода, которое будет отображаться в списке модов. Допускается использование кириллицы.
Теперь, для того, чтобы игра поняла, где начинается мод, нужно добавить начальный лейбл:
- Была объявлена метка ( label ), имя которой обязательно должно соответствовать имени мода, указанного в квадратных скобках. В нашем случае — my_mod .
Если вы хотите поменять шрифт в списке, то конструкция будет следующей:
Можно использовать как TrueType (.ttf), так и OpenType (.otf) шрифта.
Также можно добавить цвет:
И изменить размер шрифта:
# Написание сценария
Далее, в метке my_mod можно начинать писать сценарий. В нем используется специальный синтаксис Ren’Py, который мы разберем далее.
# Метки
Использование меток позволяет облегчить процесс создания мода, путем разделения сценария на части.
Имена меток должны быть уникальными во избежание конфликтов. Рекомендуется использовать названия меток, начиная с названия мода, например, my_mod_day1 .
Общий синтаксис метки выглядит так:
# Переходы между лейблами
Есть два вида переходов:
- Прыжок (jump)
В данном случае команды после "прыжка" будут пропущены игрой, например, фраза "действия после прыжка" из примера ниже не будет выведена на экран игрока. Любые другие команды, которые были написаны после прыжка также не сработают.
- Вызов (call)
В этом случае фраза из примера выше будет выведена на экран после завершения действий из метки my_mod_day2 .
Закончить блок можно командой return . После неё мод будет завершен и будет показано главное меню игры, если до этого мы не вызывали какой-либо из лейблов, а лишь прыгали по ним с помощью команды jump .
Приведём ещё один пример для наглядности:
В первом лейбле идут некие действия, затем мы вызываем второй лейбл, в котором тоже идут некие действия. Из-за того, что мы вызвали второй лейбл, а не прыгнули на него, при команде return внутри вызванного лейбла мод не завершится — нас просто выкинет обратно на первый лейбл, потому что мы прекратили ‘вызов’ второго лейбла и вернулись обратно на первый. Но! Вернулись не в самое его начало, а продолжили работу после момента с вызовом второго лейбла.
# Реплики
Реплики персонажей имеют следующий общий вид: <ID персонажа> "<Реплика>" , где:
- ID персонажа — название переменной, которой он был объявлен.
- Реплика — текст, который будет говорить персонаж.
Список персонажей и их переменные представлены в таблице по ссылке: Ресурсы игры — Персонажи.
В примере ниже представлен пример реплик Мику и Ульяны, имена которых ещё не известны:
В первом случае имя пионера или пионерки будет сменено на "Пионер/Пионерка", сохраняя свой цвет. Во втором же случае имя персонажа будет сменено на "Девочка", сохраняя свой цвет.
Смена стиля интерфейса
Есть всего 4 варианта:
- prolog_time() — Интерфейс пролога.
- day_time() — Интерфейс дня.
- sunset_time() — Интерфейс заката.
- night_time() — Интерфейс ночи.
Смена окраски спрайтов согласно времени
Всего существует 3 варианта раскраски спрайтов. Все они происходят через переменную persistent.sprite_time
- $ persistent.sprite_time = "day" — Дневная версия окраски спрайтов.
- $ persistent.sprite_time = "sunset" — Вечерняя версия окраски спрайтов.
- $ persistent.sprite_time = "night" — Ночная версия окраски спрайтов.
Пример использования смены окраски спрайтов вкупе со сменой стилей интерфейса выглядит так:
Обратите своё внимание, что если в моде не менять значение переменной смены стиля интерфейса и смены окраски спрайтов, то по умолчанию стиль интерфейса будет равен $ prologue_time() , а окраска спрайтов — $ persistent.sprite_time = "night"
# ADV и NVL режимы повествования
Существует два основных стиля изложения материала, используемых в визуальных новеллах:
ADV : Визуальные новеллы, созданные в стиле ADV, представляют собой диалог и повествование, выводимые на экран по одной строке за раз, как правило, в окне, расположенном в нижней части экрана.
NVL : Визуальные новеллы, созданные в стиле NVL, представляют собой несколько строк на экране, выводимые одновременно в окне, которое занимает весь экран.
По умолчанию меню отображаются в ADV-режиме, занимая весь экран. Существует также альтернативное представление меню в NVL-режиме, в котором меню отображаются сразу после текущей страницы текста NVL-режима.
Для перехода в NVL-режим повествования используйте следующую команду: $ set_mode_nvl()
Для перехода обратно в ADV-режим повествования используйте следующее: $ set_mode_adv()
Примеры перехода в NVL и ADV режимы повествования:
Плавные переходы окон
Не забывайте про плавные переходы для окон, в которых ведётся повествование.
- window hide — плавное скрытие диалогового окна.
- window show — плавное появление диалогового окна.
- nvl show dissolve — плавное появление NVL-окна.
- nvl hide dissolve — плавное скрытие NVL-окна.
Пример использования плавных переходов окон выглядит так:
Появление персонажа в NVL-режиме
Персонажи могут быть объявлены для использования в NVL-режиме путем создания ещё одного персонажа, но с добавлением параметра kind=nvl . Например:
Если этого не сделать, то внутри nvl-режима повествования персонажи без параметра kind=nvl будут говорить в adv-режиме.
Обратите своё внимание, что можно сделать и по другому — сделать цикл, который будет менять объявление персонажей в зависимости от текущего режима повествования. Именно такой способ и используется в БЛ.
# Оформление текста
Примеры текстовых тегов:
- alpha
Текстовый тег alpha отображает текст, расположенный между самим тегом и его закрывающим тегом, с указанной непрозрачностью. Непрозрачность должна иметь значение между 0.0 и 1.0, что соответствует полной прозрачности и полной непрозрачности соответственно. Если значение начинается с префикса + (добавить на) или — (убавить на), непрозрачность будет изменена на указанное число, а не полностью заменена. Если значение начинается с префикса * (умножить на), непрозрачность будет умножена на это число.
- b (bold)
Тег жирного шрифта выводит текст, расположенный между самим тегом и его закрывающим тегом, жирным шрифтом.
- color
Текстовый тег color отображает текст, расположенный между самим тегом и его закрывающим тегом, в указанном цвете. Цвет должен быть в формате #rgb, #rgba, #rrggbb или #rrggbbaa.
- i (italic)
Тег курсива отображает текст, расположенный между самим тегом и его закрывающим тегом, курсивом.
- s (strikethrough)
Тег зачеркивания проводит черту через текст, расположенный между тегом и его закрывающим тегом.
- u (underline)
Тег подчеркивания подчеркивает текст, расположенный между самим тегом и его закрывающим тегом.
- w (wait)
Тег ожидание – самозакрывающийся тег, который ждёт, пока читатель нажмёт на кнопку для продолжения. Если для тега задан аргумент в форме числа,то ожидание автоматически заканчивается, когда заданные секунды проходят.
Полный список текстовых тегов можно найти внутри соответствующей статьи в документации Ren’Py
# Бэкграунды [БГ]
Общий синтаксис для вывода фона: scene <Название фона> или show <Название фона>
Разница между scene и show
В первом случае команда очищает все слои и показывает изображение, во втором — просто показывает изображение поверх других. Приведём пример:
Это был пример с использованием scene для показа изображения. Фона, в нашем случае.
А здесь была использована команда show , которая лишь сменила фон на другой, не затрагивая другие изображения. Почему в нашем случае оно сменило только фон, а не показало изображение поверх всех, смотрите ниже.
В данном случае, из-за того, что у фона имеется отступ после слова bg , слово bg сработало как "тэг" и сменился только фон, а не показался новый поверх спрайтов (А если бы изображение было без тэга и показалось поверх всего, то если бы мы его убрали про помощи hide , мы бы снова увидели нашу дневную площадь и спрайты девушек). Более подробно об этом рассказано чуть ниже.
Фоны из игры представлены в таблице по ссылке: Ресурсы игры — Изображения — Фоны.
# Иллюстрации [ЦГ]
Общий синтаксис для вывода иллюстраций: scene <Название арта> или show <Название арта>
Все иллюстрации из игры представлены в таблице по ссылке: Ресурсы игры — Изображения — CG.
# Спрайты
Вызывается спрайт с помощью: show <Имя спрайта>
Обычно спрайты состоят из слов, разделённых пробелом: <имя персонажа> <эмоция> <одежда>
В оригинальной игре имя персонажа совпадает с ID говорящего из предыдущего раздела этого руководства
Список всех спрайтов пока можно найти здесь
Если персонаж уже на экране, то повторное использование show будет менять эмоцию и/или одежду, если при повторном использовании у персонажа имеется "тэг". Скажем, в команде show un cry sport — un выступает в качестве "тэга" персонажа, поэтому при смене одежды/эмоции не нужно будет убирать предыдущую картинку. Точно также тэги работают и с изображениями по типу БГ, ЦГ, и прочих.
Для того, чтобы убрать персонажа, воспользуйтесь: hide <Имя персонажа>
Если вы хотите вслед за этим сменить декорации, то прописывать hide для каждого персонажа не обязательно, команда scene сама их уберет.
# Действия с изображениями
# Позиционирование
При простом использовании show <Спрайт> он будет появляться просто по центру, это можно исправить, добавив в конец at <Позиция> : show <Спрайт> at <Позиция> .
Всего в игре 7 позиций где может находиться спрайт:
- fleft
- left
- cleft
- center
- cright
- right
- fright

На скриншоте выше были использованы следующие команды:
Также, если не хотите использовать стандартные расположения спрайтов, можно сделать свои собственные! Для этого необходимо показать спрайт, а затем прописать его расположение по x и y координатам. Для этого используем команду center , куда вписываем кортеж float чисел. Первое число — x координата, вторая — y координата.
Обращаем внимание, что позиционирование идёт по center , а не по align или pos .
Так же можно показать персонажа ближе / дальше. Для этого можно воспользоваться атрибутом close / far .

На скриншоте выше как раз были использованы эти атрибуты. Команды:
# Анимации появления
Мы можем показать спрайты, bg и cg с некоторым замедлением, плавно.
- Плавность
scene <Название> with <Атрибут>
Атрибутов для плавности 6, они отличаются лишь своей скоростью:
- dspr — 0,2 сек — Самый быстрый, на практике не особо заметен. Оптимален для смены эмоций спрайтов.
- dissolve_fast — 0.5 сек.
- dissolve — также 0.5 сек. Оптимален для смены BG/CG.
- dissolve2 — 2 сек — хороший вариант для длинных переходов между локациями лагеря
- hell_dissolve — 50 секунд — на практике не особо применим, но вдруг пригодится.
- dissolve_long — 100 секунд.
Также можно группировать несколько объектов для одновременного начала эффекта:
В приведенном примере мы попадем в ночной автобус, и перед нами предстанет улыбающаяся Славя. Все это с задержкой в 2 секунды.
Если все вышеприведённые примеры Вас не устраивают, можно добавить свой атрибут плавности. Для этого, пропишите его в блоке init.
- Моргание
Я более чем уверен, что вы видели эффект того, как иногда ГГ моргает или вовсе закрывает глаза. Мы можем реализовать подобную возможность!
- show blink — Закрыть глаза
- show unblink — Открыть глаза
- show blinking — Моргание
blink и unblink это разные эффекты, они не могут отменить друг друга.
Так же к эффектам моргания можно применить атрибут плавности.
# Добавление своих изображений
Вполне может быть, что по сюжету Вашего мода, может не хватить имеющихся БГ, ЦГ и спрайтов. В таком случае, мы добавим свои.
Для начала нам надо объявить изображение в блоке init . Делается это, с помощью объявления переменной image . Например, если есть изображение city.jpg , и оно находится в папке game/mods/my_mod/city.jpg , то объявить его можно вот так:
И использовать его:
Тэги к изображениям
Настоятельно рекомендую использовать тэги. В приведённом ниже примере слово bg выступает в виде тэга к изображению. Если объявить несколько БГ с таким тегом, то при показе следующего он автоматически заменит предыдущий.
Более детальную информацию про ATL
(opens new window) смотрите в продвинутом руководстве.
# Звуки
Ren’Py поддерживает воспроизведение музыки и звуковых эффектов, используя следующие форматы аудио файлов: Opus , Ogg Vorbis , mp3 , wav .
# Добавление звуков, музыки, эмбиенса
$ <Название аудиофайла> = <Путь к аудиофайлу>
Добавление различных аудио файлов в ваш мод происходит посредством команды, приведённой выше. Приведём пример использования.
# Музыка
Для начала проигрывания музыки используется: play music <Название> , а для остановки — stop music .
Список музыки из игры представлен в таблице по ссылке: Ресурсы игры — Звуки — Музыка.
# Окружение
play ambience <Название>
Звуки окружения из игры представлены в таблице по ссылке: Ресурсы игры — Звуки — Окружение.
# Прочее
play sound <Название>
Прочие звуки из игры представлены в таблице по ссылке: Ресурсы — Звуки — Прочие звуки.
# Плавный вход/выход музыки
Команды fadein и fadeout являются необязательными. fadeout дает время затухания для текущей проигрываемой музыки в секундах, в то время как fadein дает время, необходимое для плавного "входа" новой музыки.
# Зацикливание и разцикливание музыки
Команды loop и noloop также являются необязательными. loop заставляет музыку зацикливаться, в то время как noloop заставляет ее играть только один раз. Если ни один из них не задан, используется значение канала по умолчанию.
# Поочерёдное воспроизведение
Оператор queue используется для создания очереди аудио файлов. Они будут воспроизведены, когда канал закончит воспроизведение текущего воспроизводимого файла, если таковой имеется.
Команда для кортежа воспроизводимых файлов начинается с ключевого слова queue , за которым следует имя канала для воспроизведения звука. Он опционально принимает команды fadein , loop и noloop .
Также queue поддерживает параметры loop и fadein .
# Видео
Ren’Py предусматривает возможность использования встроенной версии Libav для воспроизведения видеороликов с такими форматами, как: .webm , .matroska , .ogg , .avi
# Полноэкранные видеоролики
Самый простой способ отображения видео в полноэкранном режиме заключается в использовании функции renpy.movie_cutscene . Она отображает видео в полноэкранном режиме до тех пор, пока оно не закончится, либо пока игрок не щелкнет кнопкой мыши, чтобы прекратить воспроизведение.
# Видео, как отображаемые объекты и спрайты
Видеоролик, отображаемый на экране посредством команды Movie , можно использовать для отображения в любом месте, где Ren’Py может его показать. Например, видео может выводиться как фон экрана меню или в качестве фона.
Отображаемый видеоролик также можно использовать для определения видео спрайта, который представляет собой спрайт, склеенный из двух видео. Первый видеоролик обеспечивает цвет спрайта. Второй, — так называемый, "маска-ролик", — обеспечивает альфа-канал, где белый цвет — полная непрозрачность, а чёрный — полная прозрачность.
Видео, которые воспроизводятся в отображаемом объекте Movie , зацикливаются автоматически.
Movie принимает два параметра:
play — строка, содержащая имя воспроизводимого видеофайла. Параметр всегда должен быть задан.
mask — строка, содержащая наименование видеофайла для использования в качестве альфа-маски. Она должна быть того же размера, продолжительности и частоты кадров, что и видеофайл, заданный в play .
Вот пример определения видео спрайта:
Видео спрайт можно показать с помощью оператора show , который автоматически запускает воспроизведение видео. Он будет автоматически остановлен при скрытии отображаемого объекта.
Видеоролик, прописанный через Movie также можно использовать как часть экрана, при условии, что он создан во время фазы инициализации (init-блок) (например, как часть оператора image).
Экраны можно прописывать и вне init-блока.
Несколько отображаемых видеороликов, прописанных через Movie , или спрайтов могут отображаться на экране одновременно с учетом производительности системы и при условии, что все они имеют одинаковую частоту кадров. Поведение Ren’Py при отображении видеороликов с разной частотой кадров не определено, но, скорее всего, будет включать значительную потерю кадров.
-
window hide
Чтобы скрыть.
-
Ещё движок может показывать текст поверх экрана, а не внизу. Этот режим называется — NVL, в то время как привычный нам — ADV. Команды связанные с этим:
-
$ set_mode_nvl()
Чтобы показать поверх экрана.
Если вы хотите использовать речь в этом режиме, то вам будет необходимо создать нового персонажа, и в его код (в скобки) добавить kind=nvl. И имена таких персонажей рекомендуется писать навроде этого:
Не забывая про пробел после двоеточия.
Пример полного кода:
Дабы не смотреть на текст на чёрном фоне, рассказывая о красоте пляжа, стоит добавить фон. Этим мы сейчас и займёмся.
Не забываем про 4 пробела, они пишутся всегда. Исключения только init и label.
Чтобы на нашем экране появился фон или любая другая картинка, нам нужно прописать одну из этих команд:
-
scene название_сцены
Для показа сцены. То есть — фона. При переходе со сцены на сцену все спрайты остаются на предыдущей.
Но опять же, всё происходит слишком резко. Так не пойдёт!
Где взять все коды BG и CG смотрите в разделе Все необходимые коды.
===========================================================================
Чтобы добавить эффект к появлению или исчезанию изображения добавляем в конец команды, после названия изображения, команду — with:
Не забываем про 4 пробела, они пишутся всегда. Исключения только init и label.
Помимо dissolve движок имеет множество других эффектов: