Система выборов и переход между сценами в зависимости от ответа игрока

Самый важный и стандартный способ интерактивности в ВН — выборы. Именно благодаря им новелла перестает быть кинетической и дарит более-менее игровой опыт.

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

Чтобы создать варианты ответа, используем команду menu — она создаст поясняющий текст внизу (необязательно) и кнопки вариантов ответа, которые будут перекидывать нас к нужным label через jump

Это позволит нам базово перемещаться по разным частям кода.

Между вариантом ответа и jump можно написать дополнительный текст в этом же label, если хочется.

label start:

	menu:
		"Выбери свой вариант ответа." # текст, который выводится внизу
		# можно убрать эту строчку, если текст снизу не нужен

		"Выбираю первое": # первый вариант ответа
			jump root_one

		"Выбираю второе": # второй вариант ответа
			jump root_two

	return

Запоминание ответа и его использование

define hungry_alice = True

label start:

	menu:
		"Поделиться с Алисой едой?"

		"Съесть свой обед самой":

			"Подруга осталась голодной." 
			# ничего не поменялось

		"Отдать ланчбокс Алисе":

			"Алиса впервые за сегодня поела!" 
			# изменили состояние персонажа

			$ hungry_alice = False
	
		return

Иногда по сюжету необходимо, чтобы игра запоминала предыдущие действия — для этого используются логические переменные. Работают они по принципу Правда-Ложь (True-False).

Чтобы ввести логическую переменную в игру, нужно в самом начале в разделе с переменными define по принципу define название_переменной = False и потом в коде нужно будет в меню (необязательно) вызвать команду, которая переключит переменную на противоположное значение $ название_переменной = True и игра запомнит это.

Проверка логической переменной через If

if название_переменной:
	"Текст, если переменная True"
else:
	"Текст, если переменная False"

<aside> <img src="/icons/asterisk_blue.svg" alt="/icons/asterisk_blue.svg" width="40px" /> Такую проверку можно вставлять в любую часть кода и делать вариативные куски новеллы.

</aside>


Примеры более сложного использования логических переменных

Если у нас есть несколько логических переменных:

if название_первой_переменной and название_второй_переменной:
	"Текст, если True у обоих переменных"
elif название_первой_переменной or название_второй_переменной:
	"Текст, если хотя бы у одной из переменных True"
else:
	"Текст, если переменная False"

Если мы хотим сделать секретный вариант ответа, доступный только при конкретных логических переменных:

label start:

	menu:
		"Выбери свой вариант ответа." # текст, который выводится внизу
		# можно убрать эту строчку, если текст снизу не нужен

		"Выбираю первое": # первый вариант ответа
			jump root_one

		"Выбираю второе": # второй вариант ответа
			jump root_two

		"Выбираю секретное третье" if название_первой_переменной and название_второй_переменной:
			jump root_secret

	return

Ввести имя (и не только)

Любая введенная игроком информация — переменная. Давайте начнем с имени, как с самой простой для использования вводимой переменной.

Вместо имени персонажа пишем [переменная_name]

Untitled

После этого предлагаем игроку ввести имя. Добавляем код ниже в нужную нам сцену внутри label:

$ e_name = renpy.input("Введите имя")

Теперь, чтобы использовать введенное игроком слово в новелле, вместо имени героини вставляем [e_name]

Untitled

Untitled

<aside> <img src="/icons/bookmark_blue.svg" alt="/icons/bookmark_blue.svg" width="40px" /> По точно такому же алгоритму мы можем добавлять ЛЮБЫЕ вводимые переменные.

</aside>


Ограничения для ввода

Чтобы игрок не написал миллион пробелов, добавляем в конец вызова ввода .strip()

$ e_name = renpy.input("Введите имя").strip()

Чтобы ограничить ввод по количеству символов, добавляем после приветственного текста “Введите имя”, length=ЧИСЛО

$ e_name = renpy.input("Введите имя", length=5).strip()

Чтобы игрок писал только нужные символы, добавляем после приветственного текста “Введите имя”, allow="символы"

	$ e_name = renpy.input("Введите имя", allow="йцукенгшщзхъфывапролджэячсмитьбю-ЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮ")
	$ e_name = renpy.input("Введите имя", allow="1234567890")

Чтобы добавить введенную переменную по умолчанию (например, дефолтное имя), добавляем после приветственного текста “Введите имя”, default="Умолчание"

$ e_name = renpy.input("Введите имя", default="Ив")

Если вдруг игрок не будет ничего вводить, то после строки с вызовом ввода переменной добавляем:

if e_name == "":
	$ e_name = "Ив"

По этой же логике можно делать пасхалки, секретные концовки или проверки корректности введенной информации:

if e_name == "Санс":
	# какая-то концовка через jump
	# переход на правильные и неправильные пути
	# какая-то смешная фраза от рассказчика через ""

<aside> <img src="/icons/downward_blue.svg" alt="/icons/downward_blue.svg" width="40px" /> Соответственно, наш финальный код на ввод имени может выглядеть вот так:

</aside>

$ e_name = renpy.input("Введите имя", length=5, allow="йцукенгшщзхъфывапролджэячсмитьбю-ЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮ", default="Ив").strip()

if e_name == "":
	$ e_name = "Ив"
	
# ИЛИ если мы хотим сделать проверку на правильность, например, числового кода:

if e_name == "35":
	"Правильно"
elif e_name != 35
	"Неправильно"
else:
	"Неправильно"

Числовые переменные

define money = 100

label start:

	menu:
		"Поделиться ли деньгами с Алисой?"

		"Я отдам ей часть своих денег":
			call money
			jump root_one

		"Я не буду давать ей деньги":
			jump root_two

	return

label money

	$ lunch_money = renpy.input("Сколько отдашь?", length=3, allow="1234567890").strip() or "0"
	$ lunch_money = int(lunch_money)

# можно сделать различные сложные условия
	if lunch_money > money: 
		$ lunch_money = money

	if lunch_money == 0:
		"Ты передумала отдавать Алисе деньги."
	elif lunch_money == money:
		"Ты отдала ей все деньги."
	else:
		"Ты отдала ей [lunch_money] денег."

	$ money = money - lunch_money

	"У тебя осталось [money] денег."

	return

Как и с логической переменной, чтобы добавить числовую, пишем в начале кода define название_переменной = число

Чтобы в большом коде облегчить себе задачу, создадим отдельный label под эту переменную. На вариантах ответа отсылаться к этому label мы будем через комадну call — она похожа на jump, но когда вызванный label проигрывается до конца return, то возвращается к той части кода, где был вызван, в то время как return после jump завершает игру.

<aside> <img src="/icons/asterisk_blue.svg" alt="/icons/asterisk_blue.svg" width="40px" /> Важно понимать, что для RenPy 5 и “5” — это разные сущности. Все, что находится в кавычках, программа понимает как текст, даже если там написано число. Все, что вводит игрок — текст, и если это число, нужно перевести его в настоящее число, считываемое программой. Для этого используется команда int(название_переменной)

</aside>

Можно использовать if название_переменной > (любой знак) число, чтобы сделать секретный вариант ответа.

Как изменить значение числовой переменной

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

define moral = 0

# и потом где-то в коде после варианта ответа, например, пишем:
$ moral = moral - 1 # вводим знак в зависимости от желаемого влияния на мораль

Чтобы сравнить значение нескольких переменных, используем if название_первой_переменной > (любой знак) название_второй_переменной. В начале кода, конечно, нужно через define прописать значения этих переменных.

Анимируем персонажей, фоны и что угодно

Слайдшоу

Мы можем создать зацикленную анимацию чего угодно, вставив в начало script.rpy следующий код:

image slideshow: # можно писать столько картинок, сколько угодно
	"image/bg library.png" #with fade
	pause 3.0
	"image/bg footballfield.png" #with dissolve
	pause 2.2
	repeat # зацикливает анимацию

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

image eve blink:
	"eve neutral"
	choice: # несколько choice подряд зарандомизируют длину паузы
		pause 2
	choice:
		pause 4
	choice:
		pause 6
	"eve laugh"
	0.25 # слово pause можно убирать, потому renpy понимает, что это число для задержки картинки
	repeat

Анимации по траекториям

Заставить картинку крутиться вокруг своей оси:

image название:
	"название картинки"
	rotate 0
	linear 10 rotate 360 # первое - скорость, второе - на сколько градусов повернуть
	repeat

Сделать кастомную трансформацию. Какие бывают параметры трансформации, можно прочитать в документации.

transform название_трансформации:
	параметр_трансформации 0 alpha 0 xpos 960 ypos 540 anchor (0.5, 0.5)
	linear 3 параметр_трансформации 2 alpha 1
	# можно делать столько строк, насколько разнообразную анимацию хотите
	
show картинка at название_трансформации

Один и тот же параметр в двух строчках с разными значениями создаст анимацию

alpha позволяет играть с прозрачностью, где 0 = прозрачно, 1 = непрозрачно.

xpos и ypos позволяют выровнять картинку по пикселям (ориентируйтесь на 1920х1080 или размер игры)

anchor (0.5, 0.5) позволяет отцентрировать трансформации по картинке