Академический Документы
Профессиональный Документы
Культура Документы
Ren’Py
2018 Ren’Py
Изучаем
Ren’Py
Разработка визуальных
новелл, rpg и создание
приложений
Романов Сергей (Andredron)
2
2018 Ren’Py
Содержание
Благодарности
Введение
Для кого написана данная книга
Почему именно Ren’Py?
Философия питона
Основы. Начало работы
Ориентирование в главном меню Launcher Ren’Py
Знакомство с текстовым редактором jEdit
Прописываем персонажей в проект
Меню, прыжки, вызовы
Комментарии
3 способа прописать изображение в проект
Фоновое изображение
Спрайт и вызываемые слои изображений
Изображение которое меняется от значения переменной
Основные ошибки при написании ConditionSwitch
Создаем спрайт из нескольких изображений
Как убрать объект
Слои в ренпае
Стандартные координаты изображений [Таблица]
Дробные значение [Таблица]
Точные значения [Инструмент]
Как поменять фон, что бы в нем не пропали обьекты другие
3 способа прописать скорость текста
3
2018 Ren’Py
13) kind=nvl
14) ctc
Изображение, которое ставят в конце диалога
1) Пример из обучения
2) Мой пример
Изображение за диалоговым окном
1) пример из обучения
2) Мой пример
3) Пример из леммафорума 1
4)Пример из леммафорума 2. Вверх вниз
стрелка
5) Пример из леммафорума 3. Анимация
15) dynamic
16) voice_tag
Подробный разбор текстовых тег [Список]:
1) Добавить спец символы в ренпай \"
2) Строку перенести ниже \n
3) Полужирное начертание {b}
4) Курсивное начертание {i}
5)Подчеркивание текста {u}
6)Добавление линии, проходящее посередине текста {s}
7) Увеличить размер текста {size=+число}
8)Уменьшить размер текста {size=-число}
11)Вставить изображение или смайл в текст
{image=exclamation.png}
12)Поменять цвет текста{color=#008000}
5
2018 Ren’Py
6
2018 Ren’Py
2)Персонаж vcentered
3)Персонаж extend
4)Персонаж expression
Подробный раздел координат изображений
Подробный раздел трансформаций[Список]
1)Смена фона с переходом (например, растворение)
2)Телепорт
3) Интерполяция времени linear
4) ZOOM ZOOM
5) Size
6)Альфа
8) Сrop. Обрезка
9) Алт трансформация
10) Оператор Вlock и time. Братья неразлучные
11) Оператор Parallel
1) Магия среди нас
2) Изображение скачет по экрану на все 4 стороны.
12) Оператор Сhoice
13) Выходим за пределы экрана.
14) Блок on
1)Кнопки
2)Растворение
3) Как задать спец мелодию при пропуске.
15) Contains
16) Function
17)Различные интерполяции Warpers
7
2018 Ren’Py
9
2018 Ren’Py
11
2018 Ren’Py
Splashscreen
Метка splashscreen
Так же его можно модернизировать, прописать кнопку
пропуск сцены
Или задать одноразовый вопрос пользователю, А тебе
точно есть 18?
Изображение splashscreen
Экраны
Правильный пример как прописывать экран:
Как отобразить экран в проекте
Экран с 3 параметрами
Несколько параметров экранов
1) modal True
2)Zorder
3)style_prefix
4) tag menu
Python в экранах
Операторе default
Операторы if, elif, else
Оператор for
Оператор Frame(рамка для экрана)
Как убрать стандартную рамку в экране
Оператор Add и как добавить изображение в глав меню
Как прописать изображения в главное меню?
Оператор text
Как прописать музыку в экране
12
2018 Ren’Py
13
2018 Ren’Py
14
2018 Ren’Py
Viewport
1)Вертикальные и горизонтальные полосы (scrollbars "both")
2) Горизонтальные полосы (scrollbars "horizontal")
3) Вертикальная полоса( scrollbars "vertical")
Как установить начальную зону просмотра.(xinitial и yinitial)
Как клонировать обьекты в порте
Пример скрола с огромным числом текста
Drag and Drop
Экран загрузки
Подробный разбор значений drag
Как перенести изображение в область где должно
произойти событие
Простой способ смены суток
Простейший календарь
Прописываем отображение денег
Часы электронные и цифровые
Вызов call из экрана screen
Информационный экран, пополняемый
Информационный экран 2. Лист персонажа
Листаем страницы книги
Стили
Через стиль можно задать координаты
Через стиль можно задать размеры рамки
Изменяем текст воспроизведения для синтезатора речи
Удобный способ написания стиля в экранах
Настройки текста стиля в экранах и в персонажах
15
2018 Ren’Py
Вертикальный текст
Жирный текст
Курсивный текст
Нижнее подчеркивание
Цвет тексту
Шрифт тексту
Обводка теста
Сглаживание текста
Интервал расстояния текста
Отступ 1 строки текста
Дополнительный пробел между словами
Расстояние между каждой буквой
Интервал над строками
интервал под строками
Минимальная ширина строки
Скорость появления имени персонажа
Скорость диалога персонажа
зачеркнуть текст
Стиль рамок
Задний фон
Изменяем размеры внутри фона кнопки
Изменяем размеры вне фона кнопки
Передний фон
Сделать одинаковым размером все кнопки
Стиль кнопок
Звук при наведении и нажатии
16
2018 Ren’Py
Видео
Как проиграть видеозаставку до появления главного меню
Как добавить видео фоном
Как добавить видео-спрайт.
Как указать видео координаты
Как отключить возможность пропуска видео.
Режим разработчика
Клавиши которые работают в режиме разработчика
Интерактивный директор
Изменяем директора
Ввод имени персонажа
1)Пример из обучения
2) Более продуманный способ
3)Пример из хот спота
4) Прописываем имя и фамилию персонажа
5) "Герой без конкретного имени"
Имя пользователя которая прописана на вашем компьюторе
Создаем экранную клавиатуру
Генераторы случайных чисел
1) renpy.random.choice
17
2018 Ren’Py
Простой словарь
Работа со словарями
Обращение к значениям в словаре
Добавление новых пар «ключ—значение»
Создание пустого словаря
Изменение значений в словаре
Удаление пар «ключ—значение»
Словарь с однотипными объектами
Перебор всех пар «ключ—значение»
Перебор всех ключей в словаре
Упорядоченный перебор ключей словаря
Перебор всех значений в словаре
Список в словаре
Словарь в словаре
Циклы while
Пользователь решает прервать работу программы
Флаги
Использование цикла while со списками и словарями
Удаление всех вхождений конкретного значения из списка
Заполнение словаря данными, введенными пользователем
Функции
Определение функции
Необязательные аргументы
Возвращение словаря
Использование функции в цикле while
Изменение списка в функции
21
2018 Ren’Py
22
2018 Ren’Py
БЛАГОДАРНОСТИ
23
2018 Ren’Py
ВВЕДЕНИЕ
24
2018 Ren’Py
Цель этой книги – как можно быстрей ввести читателя в курс дела, что
бы тот мог писать на Ren’Py работоспособные приложения (игр,
визуализация данных), и одновременно заложить основу в области
программирования, которая ему пригодится на протяжении всей
жизни. Книга написана для людей, которые прежде никогда не
программировали на Python или вообще никогда не программировали.
ФИЛОСОФИЯ PYTHON
Долгое время язык программирования Perl был краеугольным камнем
интернет-программирования. На первых порах функционирование
многих интерактивных сайтов было основано на сценариях Perl. В то
время сообщество Perl руководствовалось девизом: «Это можно
сделать несколькими способами». Какое-то время разработчикам
нравился такой подход, потому что гибкость, присущая языку,
позволяла решать многие задачи разными способами. Подобный
подход был допустим при работе над собственными проектами, но со
временем стало ясно, что чрезмерная гибкость усложняет
долгосрочное сопровождение крупных проектов. Было слишком
трудно, утомительно и долго разбираться в коде и пытаться понять,
что же думал другой разработчик при решении сложной задачи.
Опытные программисты Python рекомендуют избегать лишних
сложностей и применять простые решения там, где это возможно.
25
2018 Ren’Py
26
2018 Ren’Py
ОСНОВЫ
27
2018 Ren’Py
НАЧАЛО РАБОТЫ
В этой части книги будут представлены базовые концепции
необходимые для написания программы.
Для начало работы вам необходимо будет правильно установить
Ren’Py
1) Скачайте Launcher Ren’Py http://www.renpy.org и выберите самую
последнюю версию
2) Установите его C:\Program Files\RenPy На пути установки не
должно быть иных символов кроме английского
3) Запустите его.
У вас высветится такое окно:
28
2018 Ren’Py
Для удобства работы, выберите ваш язык, для этого вам необходимо
будет выбрать Preferences (он обведен красным кружком) Найдите в
нем строку Languages и выберите пункт Russian.
Далее вам потребуется выбрать папку, где у вас будут создаваться
все проекты.
Для этого выберите раздел Настройки и нажмите на пункт Папка
проектов
Теперь все ваши проекты будут отображаться в выбранной вами
папке.
В Ren’Py существует 2 версии темы – старая и новая(GUI). Чем скорей
вы перейдете на новую версию(GUI) тем лучше. Все же полезней
использовать самую новую версию.
29
2018 Ren’Py
30
2018 Ren’Py
31
2018 Ren’Py
32
2018 Ren’Py
33
2018 Ren’Py
ЗНАКОМСТВО С JEDIT
34
2018 Ren’Py
Приступим к работе
35
2018 Ren’Py
Вам нужно создать метку(label), на которую ren’py будет ссылаться. Стандартная метка, с
которой начинаются все приложения ренпая - называется start.
36
2018 Ren’Py
37
2018 Ren’Py
38
2018 Ren’Py
39
2018 Ren’Py
init:
define katya = Character(_("Катя"), color="#008000", who_suffix = ':')
define shora = Character(_("Георг"), color="#008000", who_suffix =
':')
katya и shora – имена ссылки, мы будем вызывать данные имена в
проект что бы нам меньше писать в нем кода.
Character(_("Катя"), - персонаж с именем Катя, нижнее
подчеркивание необходимо для того что бы данный текст отобразился
в переводе
color="#008000", - Мы прописываем цвет имени персонажа, в нем
используются цветовая палитра. Весь список цветов вы можете
рассмотреть в гугле, также код необходимо заключать в кавычки.
Обратите внимание, если вы хотите сделать текст полупрозрачным,
вместо 6 знатного кода вам необходимо писать 8 чисел, первые 6 –
код цвета, следующие 2 цифры - % прозрачности. color="#00800085"
who_suffix = ':'- символ который будет после имени персонажа.
Больше команд и значений смотрите в Продвинутый разбор
Character
Теперь рассмотрим, как же вызывать короткие имена-ссылки
персонажей.
Зайдите в текстовом редакторе в файл-сценарий script.rpy и
запишите следующий текст:
label start:
"Раздался звонок в дверь"
40
2018 Ren’Py
41
2018 Ren’Py
42
2018 Ren’Py
43
2018 Ren’Py
КОММЕНТАРИИ
Комментарии – это то, что пишется после символа #, и представляет
интерес лишь как заметка для читающего программу.
44
2018 Ren’Py
https://tproger.ru/articles/comments-in-code/
ПРЫЖКИ
45
2018 Ren’Py
label kafe:
"Мы вместе классно посидели, пообщались "
"Давно я так не болтал с таким близким человеком"
Пропишите следующее в internet.rpy:
label internet:
"Катя ушла"
"Я решил сесть пообщаться с собеседниками в интернете"
И в script.rpy
label start:
"Раздался звонок в дверь"
"Открыв его, я увидел свою лучшую подругу"
katya "Привет!!!"
katya "Ты гулять идешь? Ммм?"
shora "Привет, я сегодня…"
menu:
"1) Буду занят":
shora "…буду занят, прости"
katya "Блин жалко…."
katya "Завтра расскажи чем занят был то, хорошо?"
shora "Хорошо"
jump internet
"2) Свободен":
46
2018 Ren’Py
shora "…свободен.."
katya "Класс!!!"
katya "Пошли тогда в кафешку перекусим!"
katya "Я сегодня сутра ничего не ела!"
shora "подожди 1 минуту я переоденусь"
jump kafe
"Я лег спать"
"Меня разбудило сообщение в телефоне"
Сохраните изменения и запустите проект
CALL
Подкорректируем наши записи в script.rpy
label start:
"Раздался звонок в дверь"
"Открыв его, я увидел свою лучшую подругу"
katya "Привет!!!"
katya "Ты гулять идешь? Ммм?"
shora "Привет, я сегодня…"
menu:
47
2018 Ren’Py
ДОБАВЛЯЕМ ИЗОБРАЖЕНИЕ В
ПРОЕКТ
init python:
config.automatic_images_minimum_components = 1 ###
минимальное количество тегов
config.automatic_images = [' ', '_', '/'] ### список разделителей для
создания тегов
config.automatic_images_strip = ["images"] ### здесь через запятую
можно указать и другие папки из директории game
49
2018 Ren’Py
ФОНОВОЕ ИЗОБРАЖЕНИЕ
label start:
scene black
"У нас черный задний фон"
50
2018 Ren’Py
Как вы заметили,
show katya ulibaetsya
katya "Привет!!!"
katya "Ты гулять идешь? Ммм?"
show shora kazus
51
2018 Ren’Py
label start:
52
2018 Ren’Py
$ live_hp = 100
label start2:
"У тебя жизни столько [live_hp]"
"И тебя стукнули по голове книгой"
$ live_hp -25
if (live_hp < 10):
show john very
"Вырубили тебя"
return
elif (live_hp <= 50):
show john hurt
"Почти пришибли"
else:
show john
"Больно!!!!"
"Начинаем все сначало"
jump start2
53
2018 Ren’Py
"Фон поменялся!!!!"
pause
Каждая строка представляет собой уникальное сочетание из условия
(первый аргумент в кавычки) , и изображение, которое должно быть
показано , если условие истинно (второй аргумент в кавычки). В то
время как изображение на экране, Ren'Py оценит , если первое
условие истинно. Если да, то он будет показывать изображение в
сочетании с условием. Если это не так, она будет двигаться ко
второму условию и проверить его и так далее.
Для числовых переменных код будет выглядеть примерно так
54
2018 Ren’Py
Что бы посмотреть пример кода такого откройте бесконечное лето скрипты, или скачайте
и посмотрите следующий проект
https://lemmasoft.renai.us/forums/download/file.php?id=24372
Много общего с предыдущей темой, по этому в кратце запишу код что бы понятно было
init-2:
## ------------- Принцесса Елена -------------------
image ElenaG = "ch/E_g/E_Gr.png"
55
2018 Ren’Py
56
2018 Ren’Py
СЛОИ В РЕНПАЕ
Откуда взял идею http://traumendes-madchen.com/blog/?p=1395
Простой пример. Вам нужно прописать движение облаков. Задача
усложняется тем что впереди у вас стоит здание замка, и между
зданиями вам нужно провести таким образом что 1 здание было
впереди неба, а 2 позади неба.
Для начала вам нужно узнать каким образом определяются слои в
ренпае.
label start:
centered "Пролог"
scene goluboe_nebo # 1 слой он же основной слой
show zamok_2 at right # 2 слой
show oblako at dvishenie # 3 слой
show zamok_1 at left # 4 слой
$ renpy.pause(10.0, hard=True) #Жесткая пауза
centered "Хризалида{p=1}Ветер перемен"
scene black with dissolve # сцена которая убирает все
pause
1 слой – это сцена, которая будет находиться позади всех
графических обьектов.
2 слой – это половина замка, будет находиться позади облака
3 слой – облако которое не будет прятаться за голубое небо и 2
половине замка, оно будет выше их. Но оно будет заходить за 1
половину замка.
4 слой – половина замка которая находится впереди всех обьектов
scene black – мы вызываем новую сценну и все наши графические
обьекты будут удалены.
Что бы у вас не пропадали ваши анимированные сцены, когда вам
нужно сменить фон, прописывайте анимации в экранах и вызывайте
их командой show screen zamok.
Так же обращаю ваше внимание на то что чем больше у вас
57
2018 Ren’Py
СТАНДАРТНЫЕ КООРДИНАТЫ
ОБЪЕКТОВ[ТАБЛИЦА]
58
2018 Ren’Py
59
2018 Ren’Py
+------------------------------------------------------+
0 | 0 0.5 1 | 0
| |
| |
| |
| |
0.5 | | 0.5
| |
| |
| |
| |
1 | 0 0.5 1 | 1
+------------------------------------------------------+
60
2018 Ren’Py
61
2018 Ren’Py
62
2018 Ren’Py
default preferences.text_cps = 0
Измените значение на 30
default preferences.text_cps = 30
Что бы изменения были внесены, вам потребуется выйти из проекта,
зайти в лаунчер ренпая и нажать на подпункт Очистить постоянные
Вы очищаете всю информацию что у него до этого было записано
(например сколько вы прошли текста для прокрутки а так же
системную информацию)
label start:
scene dom
"{cps=25}Быстро!!!! {/cps}{cps=5}очень медленно
медленно{/cps}"
{cps=25} - начало откуда у нас происходит действие тега, и до этого
момента тег на текст не влиял.
{/cps} – окончание действие тега. После него тег не действует.
63
2018 Ren’Py
65
2018 Ren’Py
ALT АНИМАЦИИ
Анимации можно прописать отдельно, где нибудь в файле
сценария
init:
image ger_1:
"images/1/1.png"
pause 1.0
"images/1/2.png"
pause 1.0
repeat 2
и как вызвать в script.rpy
label start:
66
2018 Ren’Py
ТРАНСФОРМАЦИИ
67
2018 Ren’Py
SCREEN
Прежде чем мы перейдем изменять главное меню, стоит лучше
познакомиться с экранами.
Экраны прописывают отдельно от диалогов, что бы ни путаться
создайте screen2.rpy
И пропишите в начале строки(как метки) следующий код:
68
2018 Ren’Py
screen simple_screen():
frame:
xalign 0.5 ypos 50
vbox:
text _("Это экран.")
textbutton _("Хорошо"):
action Return(True)
script.rpy
label start:
call screen simple_screen
Оператор screen говорит ренпаю, что это экран, и у него имя
simple_screen
Объект frame: используется, что бы показать на каких координатах
будет находиться данный экран и заключить ли в рамку этот экран
Объект vbox: расставляет вертикально все, что в нем пропишут
text _("Это экран.") – текст
textbutton – текстовая кнопка
action Return(True) – действие при нажатии
1) show screen
show screen imya_ekrana
Данный экран будет показываться, пока его не скроют.
Скрывают экраны командой hide screen imya_ekrana
2) call screen
69
2018 Ren’Py
textbutton _("Школа"):
70
2018 Ren’Py
textbutton _("Дом"):
xalign 0.5 ypos 40
action [ Jump("home"), Hide("inventar") ]
textbutton _("Сумка"):
xalign 0.5 ypos 30
action Call ("inventar")
script.rpy
laber start:
"Что ты выберешь?"
call screen knopka
textbutton _("Школа"):
xalign 0.5 ypos 50
hovered Notify(_("Ты навел на кнопку"))
unhovered Notify(_("Ты отвел кнопку"))
action [Jump("shkola"), Notify(_("Ты нажал на кнопку"))]
textbutton _("Дом"):
xalign 0.5 ypos 40
hovered Notify(_("Ты навел на кнопку"))
unhovered Notify(_("Ты отвел кнопку"))
action [Jump("home"), Notify(_("Ты нажал на кнопку"))]
textbutton _("Сумка"):
xalign 0.5 ypos 30
hovered Notify(_("Ты навел на кнопку"))
unhovered Notify(_("Ты отвел кнопку"))
action [Call ("inventar"), Notify(_("Ты нажал на кнопку"))]
71
2018 Ren’Py
ГРАФИЧЕСКИЕ КНОПКИ
label start:
call screen imagebutton_example
Это мой самый любимый способ прописи графической кнопки. В нем
можно прописать модифицированные ренпаем графические
изображения(изображение цветное, а в ренпае сделали его чб)
Есть еще 1 способ, в нем автоматически берутся изображения.
screen gui_game_menu():
vbox xalign 1.0 yalign 1.0:
imagebutton auto "images/button_%s.png" action Jump('ddde')
label start:
call screen gui_game_menu
72
2018 Ren’Py
73
2018 Ren’Py
74
2018 Ren’Py
ПОДРОБНЫЙ РАЗБОР
ВОЗМОЖНОСТЕЙ РЕНПАЯ
ДИАЛОГ, И ВСЕ ЧТО ПРОПИСЫВАЕТСЯ В
ТЕКСТОВОМ ДИАЛОГЕ.
Ранее мы прописывали в ознакомительной части как правильно
писать отступы, что бы ренпай мог запустить текст диалога.
label start: ### без отступа
scene komnata with dissolve
"Раздался звонок в дверь" ### 4 отступа
"Открыв его, я увидел свою лучшую подругу" ###4 отступа
Теперь мы подробней рассмотрим коды, которые помогут вам
улучшить внешний вид вашего проекта.
75
2018 Ren’Py
МНОЖЕСТВЕННЫЙ ДИАЛОГ
Иногда нам бывает необходимо вывести фразы сразу 2 персонажей,
что бы было сразу 2 фразы, используют команду multiple. Простой
пример такого кода:
define ele = Character(_("Жена"), color="#c8ffc8")
define lua = Character(_("Муж"), color="#c8c8ff")
label start:
ele "Где ты был?! Опять со своими дружками пил?!" (multiple=2)
lua "Дорогая я сейчас тебе все объясню! Только убери подальше эту
сковородку! Пока никого не поколечила!!!" (multiple=2)
reply.rpy
# Reply and Reply2
# by xavimat (cc-by, 2013)
# inspired by fiorica's "The Doll's Stories" and SusanTheCat's "Thera'Py"
# improved with help of jw2pfd
init python:
thequestion = question
found_it = ""
ans = answers.replace(" ", "")
ans = ans.split(",")
if show_answers:
thequestion += " {size=-10}("
76
2018 Ren’Py
phrase = renpy.input(thequestion)
phrase = phrase.lower()
if found_it == "":
renpy.say(invalid_character, invalid_answer)
return found_it
thequestion = question
found_it = [ ]
ans = answers.replace(" ", "")
ans = ans.split(",")
if show_answers:
thequestion += " {size=-10}("
while found_it == [ ]:
phrase = renpy.input(thequestion)
phrase = phrase.lower()
if found_it == [ ]:
renpy.say(invalid_character, invalid_answer)
return found_it
label start:
$ r = reply("Where can we go?", "park, beach, home")
if r == 'park':
# do something
77
2018 Ren’Py
elif r == 'beach':
# do something
else:
# do something
$ l = len(r2)
if l > 2:
e "You have chosen too much."
#Note that with reply2() we don't use "elif" but separated "if" because all
of the keywords can be found. With "len()" you have the total of keywords
found in the user's reply.
1) WINDOW_
Задаем фон заднего диалогового окна
78
2018 Ren’Py
2) WHO_COLOR И WHAT_COLOR
Цвет имени и цвет диалога
define nino = Character(_("Нина"), who_color="#c8ffc8",
what_color="#ffc8c8")
Так же имени цвет можно задать командой color="#008000" вместо
who_color
define rish = Character(_('Рыжий'), color="#008000")
79
2018 Ren’Py
3) WHO_FONT И WHAT_FONT
Шрифт имени и шрифт диалога
define imya = Character(_("Имя"), who_font="font/Roboto-Regular.ttf",
what_font="font/Roboto-Light.ttf")
где "font/Roboto-Regular.ttf" путь к шрифту
4) WHAT_SIZE И WHO_SIZE
Размер букв диалога и имени
define imya = Character(_("Имя"), what_size=20, who_size=20)
5) WHAT_OUTLINES И WHO_OUTLINES
Обвести текст диалога и имени
define e5 = Character(_("Eileen"), what_outlines=[( 1, "#008000", 0, 0 )] )
Будет вот такой вид
6) WHAT_XALIGN И WHO_XALIGN
Контролирует где будет расположено в текст-боксе диалог
0.0 –Слева
80
2018 Ren’Py
0.5 –Середина
1.0 –Справа
7) WHAT_TEXTALIGN И WHO_TEXTALIGN
Контролирует, как размещаются строки текста относительно друг
друга(обычно 0.5)
define vasya2 = Character(_("Vasek"), what_textalign=0.5)
_textalign и _xalign обычно всегда приводят в единое значение
8) WHAT_LAYOUT
Длина каждой строки.
Если поставить в значение what_layout='subtitle' то каждая строка
будет пытаться стать одинаковой по длине
define e7 = Character(_("Eileen"), what_layout='subtitle')
Помимо режима одинаковых строк (subtitle) есть режим все в 1
строку(nobreak)
define e7 = Character(_("Eileen"), what_layout='nobreak')
9) NONE
Диалог без имени
define e8 = Character(None)
И пример всего, что здесь прописывалось
81
2018 Ren’Py
11) KIND
Копирует все аргументы имени-ссылки, что бы не печатать все кучу
раз то, что до этого прописывал, просто введите эту команду и
поменяйте нужные значение)
define frick = Character(kind=vasya1, what_outlines=[( 1, "#c00000", 0,
0 )] )
12) IMAGE
Добавить изображение в текст бокс
Пример. Прописываем ссылку-имя(дадим ему имя ru) на изображение
image side ru ="images/ru.png"
82
2018 Ren’Py
13) KIND=NVL
83
2018 Ren’Py
и наоборот
84
2018 Ren’Py
14) CTC
click to continue – нажми что бы продолжить
1) ПРИМЕР ИЗ ОБУЧЕНИЯ
85
2018 Ren’Py
2) МОЙ ПРИМЕР
86
2018 Ren’Py
image ctc_blink:
"GUI/arrow.png"
linear 0.75 alpha 1.0
linear 0.75 alpha 0.0
repeat
define gi = Character('Giselle',
color="#6699cc",
ctc="ctc_blink",
ctc_position="nestled")
87
2018 Ren’Py
2) МОЙ ПРИМЕР
88
2018 Ren’Py
3) ПРИМЕР ИЗ ЛЕММАФОРУМА 1
image ctc_anchored:
"GUI/arrow.png"
yalign 0.96 xalign 0.95 #Adjust these numbers to fit your own textbox
linear 0.75 alpha 1.0
linear 0.75 alpha 0.0
repeat
define gi = Character('Giselle',
color="#6699cc",
ctc="ctc_anchored",
ctc_position="fixed")
image ctc:
"GUI/arrow.png", #This is your image
subpixel True #This line makes sure that ATL is smooth
yalign 0.96 xalign 0.95 #Adjust these numbers to fit your own textbox
linear 0.5 xalign 0.955
linear 0.5 xalign 0.95
repeat
89
2018 Ren’Py
image ctc = Animation("GUI/ctc1.png", 1.0, #The second number is the time that
Ren'Py stays on this one image
"GUI/ctc2.png", 0.2,
"GUI/ctc3.png", 0.2,
xpos=1760, ypos=1000) #The position of the CTC, adjust for your own needs
15) DYNAMIC
должна быть строка, содержащая выражение питона. Эта строка
будет оценена перед каждой строкой диалога и результатом,
используемым в качестве названия символа.
(Корявый пример, дано условие if st > 5.0, и там прописываем имя Любимый,
который будет при условии st выше 5, в переменной player_name, а во всех
остальных условиях (Else) имя у персонажа будет Знакомый, а dynamic
позволяет включать питону проверку значений условий или нет)
16) VOICE_TAG
Это речевой тег, присваиваются к Character, речевые файлы(.ogg), которые
связаны с ним, могут отключать звук или воспроизводиться на
предпочтительном экране.
Пример из документации
90
2018 Ren’Py
screen voice_toggle:
vbox:
textbutton _(" Бесшумный режим Eileen ") action
ToggleVoiceMute("eileen")
textbutton _(" Бесшумный режим Lucy ") action
ToggleVoiceMute("lucy")
label start:
show screen voice_toggle
voice "e01.ogg"
e " Можно включить и выключить речь персонажа."
voice "l01.ogg"
l " Да! Теперь я могу наконец заткнуть Вас!"
voice "l02.ogg"
l " Подождите..., это означает, что они могут отключить звук мне также!
Действительно?"
Где это можно применить? простой пример Врата штейна или
Школьные дни, Кланнад – там в настройках есть режим отключить
голос определенному персонажу(или женские и мужские голоса)
91
2018 Ren’Py
92
2018 Ren’Py
label start:
"Жить хорошо {p}А хорошо жить еще лучше"
93
2018 Ren’Py
12)ПОМЕНЯТЬ ЦВЕТ
ТЕКСТА{COLOR=#008000}
label start:
scene black
15)СДЕЛАТЬ ГОРИЗОНТАЛЬНЫЙ
ТЕКСТ{HORIZ}
(вы на нем пишите автоматически)
94
2018 Ren’Py
17)ГИПЕРССЫЛКА В ТЕКСТЕ
{a=jump:a_label} прыжок в метку a_label{/a}.
{a=call:a_label} вызываем метку a_label{/a}.
Существуют также {a=show:screen} и {a=showmenu:screen}, которые
показывают экраны в игре и в контексте меню,
соответственно(например, не забудьте сохраниться и ссылка в тексте
на сохранение и т.д.).
Так же в гиперссылках есть жесткая пауза. Пока вы не выберете пункт
экран, диалог не на что не реагирует, прописывают в конце
(advance=False)
Ellen "Хотели бы Вы идти {a=jump:living_room} на запад {/a} или
{a=jump:kitchen} на север {/a}?" (advance=False)
18)СДЕЛАТЬ ТЕКСТ
ПРОЗРАЧНЫМ{ALPHA=0.1}
"{ALPHA=0.1}ЭТОТ ТЕКСТ СТАЛ ПРОЗРАЧНЕЙ НА 10%
{/ALPHA}"
95
2018 Ren’Py
"Утренний зали{cps=1}ппппп{/cps}"
20)ПОМЕНЯТЬ ШРИФТ
ТЕКСТА{FONT=DEJAVUSANS-BOLD.TTF}
label start:
22)СДЕЛАТЬ ОТСТУП
ГОРИЗОНТАЛЬНЫЙ(ПУСТОЕ
ПРОСТРАНСТВО)
" текст {space=30} текст"
23)СДЕЛАТЬ ОТСТУП
ВЕРТИКАЛЬНЫЙ(МЕЖДУ СТРОКАМИ)
{vspace=30}
24)НЕМЕДЛЕННО ПЕРЕЙТИ К
СЛЕДУЮЩЕМУ ТЕКСТУ И ИСПОЛЬЗОВАТЬ
РАЗНЫЕ ПЕРЕХОДЫ
"диалог{nw}"
with fade
"диалог"
96
2018 Ren’Py
97
2018 Ren’Py
1)КОСТЫЛЬ, НО ЧУТЬ ЛИ НЕ
ЕДИНСТВЕННОЕ РЕШЕНИЕ, ЕСЛИ У ВАС
СЛОЖНАЯ РАМКА.
98
2018 Ren’Py
Минус:
У вас проект будет весить чуть больше чем, если вы будете
пропечатывать в истинном способе
У вас должны быть базовые знания по фотошоппу или иным
приложениям.
Прописываем персонажа
define e = Character('Эйлин', color="#c8ffc8")
99
2018 Ren’Py
100
2018 Ren’Py
101
2018 Ren’Py
(http://renpyfordummies.blogspot.com/2018/05/gui.html?m=1)
# стандартные настройки меню
define gui.choice_button_width = 1280
define gui.choice_button_height = 72
define gui.choice_button_borders = Borders(150, 16, 150, 16)
102
2018 Ren’Py
init python:
# автоматическое объявление изображений
images_auto()
window_center()
103
2018 Ren’Py
label start:
menu:
"Текст по центру":
pass
"{#image=vk} Текст в центре, картинка слева":
pass
"{image=vk} Текст в центре, картинка рядом с текстом":
pass
"{#image=vk} {image=pref} Текст с картинкой в центре, картинка
слева":
pass
"{#image=vk} Картинка слева, текст справа{#align=1.0}":
pass
"{image=pref} Текст с картинкой слева{#align=.0}":
pass
"{#image=vk}{image=pref} Текст с картинкой слева и картинка
слева{#align=.25}":
pass
return
1)ПЕРСОНАЖ CENTERED
Он позволяет вам писать текст на середине экрана (диалоговое окно
убирается). Очень часто используется в сочетании черного и белого
фона. Не заменимая вщь при создании титров и пролога
scene black
centered "Первое что сказал он, когда зашел в класс"
104
2018 Ren’Py
2)ПЕРСОНАЖ VCENTERED
Все аналогично 1 персонажу только вертикально (очень удобно на нем
иероглифы прописывать)
scene black
vcentered "Первое что сказал он, когда зашел в класс"
105
2018 Ren’Py
3)ПЕРСОНАЖ EXTEND
Он позволяет расширить предыдущую строку диалога
дополнительным текстом, т.е. он позволяет делать различные вещи
во время диалога. Пример
show eileen vhappy ###Спрайт шок
extend "Кошмар,"
show eileen kosmah ###спрайт крик
extend "я деньги забыла!!!"
И получаем: идет сплошной текст: Кошмар, Я деньги забыла!!!
только после слова кошмар спрайт авт меняется, ед. условие текст
должен идти плавно, а не мгновенно. Тогда будет эффект.
4)ПЕРСОНАЖ EXPRESSION
106
2018 Ren’Py
107
2018 Ren’Py
ПОДРОБНЫЙ РАЗДЕЛ
ТРАНСФОРМАЦИЙ[СПИСОК]
label start:
scene pic_anim
Так же можно и к спрайтам с кнопками применить данную
трансформацию
2)ТЕЛЕПОРТ
init:
image pic1 = "risunok_1.png"
transform teleport:
xalign 1.0 yalign 0.0
pause 1.0
xalign 0.0
repeat
label start:
show pic1 at teleport
И наш спрайт (или фон если вместо show будет scene) будет
телепортироваться (мгновенно менять свои координаты) (с xalign 1.0
(т.е. с левой стороны) на xalign 0.0 (на правую сторону)
109
2018 Ren’Py
label start:
show logo base at z_z
110
2018 Ren’Py
4) ZOOM ZOOM
Zoom позволяет нам увеличивать или уменьшать изображение, делая
его больше или меньше.
Пишется он очень просто. Можно через анимацию алт или
трансформацию.
Анимация
image pic1 = "risunok_1.png" ###спрайт девушки в гневе
image pic2 = "risunok_2.png"###спрайт парень в шоке
label start:
show pic1 ###спрайт девушки в гневе
"Она" "Я беременна!"
show pic1: ### Девушка плавно увеличилась
zoom 1.0
linear 1.0 zoom 1.5
show pic2 at right: ###парень плавно уменьшился
zoom 1.0
linear 1.0 zoom 0.5
"Он" "Оп-па…."
111
2018 Ren’Py
112
2018 Ren’Py
label start:
show pic1_1 at toshnotiki
"Меня тошнит"
"Звук, как кто-то свой завтрак керамическому другу отдает"
scene black
show pic1
"Она" "Я беременна!"
show pic1 at hana
show pic2 at hana_emy
"Он" "Оп-па…."
А приведя значения в отрицательное значение xzoom и yzoom мы
отразим объект (зеркально) по гориз и вертикали
show logo base:
linear 1.0 xzoom -1.0 yzoom 1.0
5) SIZE
Данный оператор позволяет нам задать изображению размер (Сразу
вспоминается момент, когда хотел сделать в проекте несколько
разрешений экрана при помощи данного оператора, говорю сразу
бесполезная затея, поэтому лучше не тратьте время зря)
show logo base:
size (300, 450)
И изображение будет иметь разрешение 300 на 450
113
2018 Ren’Py
6)АЛЬФА
Данный оператор задает прозрачность к применяемому объекту.
init:
transform vszhik:
alpha 1.0
linear 1.0 alpha 0.0
linear 1.0 alpha 1.0
repeat
label start:
show pic_1 at vszhik
7) ROTATE.
Нам требуется, что бы изображение крутилось вокруг себя, в этом нам
поможет Rotate.
Пример на 360 градусов
114
2018 Ren’Py
8) СROP. ОБРЕЗКА
Вам требуется что бы персонаж выглядывал из за угла, или с
одеяла(видел пример такой) или половина тела(берегись
поез………………..) то вызывают оператора Сrop.
show logo base:
crop (0, 0, 100, 307)
Где в скобке указанно как оно будет обрезана.
Так же через него можно сфокусироваться(приблизить) на
изображении
show bg washington:
crop (0, 0, 800, 600)
size (1280, 720)
linear 4.0 crop (451, 437, 409, 230)
9) АЛТ ТРАНСФОРМАЦИЯ
Так как стандартные блоки(left, right, center….и т.д) являются
трансформациями, то мы можем их просто записать как они есть.
show eileen happy:
right
pause 1.25
left
115
2018 Ren’Py
pause 1.25
repeat
init:
116
2018 Ren’Py
parallel:
xalign .5
linear 3.0 xalign .75
linear 6.0 xalign .25
linear 3.0 xalign .5
repeat
parallel:
alpha 1.0 zoom 1.0
linear .75 alpha .5 zoom .9
linear .75 alpha 1.0 zoom 1.0
repeat
parallel:
rotate 0
linear 5 rotate 360
repeat
117
2018 Ren’Py
Изображение
118
2018 Ren’Py
119
2018 Ren’Py
14) БЛОК ON
Данный блок отвечает за 2 события – событие включено и отключено.
И оно тем самым создает условия и значения при вкл и откл
1)КНОПКИ
init:
transform pulse_button:
on hover:
linear .25 zoom 1.25
linear .25 zoom 1.0
on idle:
linear .25 zoom 1.0
linear .25 zoom 1.25
screen navigation():
vbox:
style_prefix "navigation"
xpos gui.navigation_xpos
yalign 0.5
spacing gui.navigation_spacing
if main_menu:
120
2018 Ren’Py
else:
2)РАСТВОРЕНИЕ
init:
transform logo_base:
on show:
alpha 0.0
linear .5 alpha 1.0
on hide:
linear .5 alpha 0.0
on replace:
linear 2.0 alpha 1.0
on replaced:
linear 2.0 alpha 0.0
repeat
label start:
121
2018 Ren’Py
screen skip_indicator():
on 'show' action Play('music', 'faster.mp3')
on 'hide' action Play('music', 'normal.mp3')
15) CONTAINS
Оператор contains позволяет применять к уже прописанной трансформации
еще операторов.
init:
transform an_animation:
"1.png"
pause 2
"2.png"
pause 2
repeat
image move_an_animation:
contains an_animation
xalign 0.0
linear 1.0 yalign 1.0
122
2018 Ren’Py
16) FUNCTION
init python:
def slide_function(trans, st, at):
if st > 1.0:
trans.xalign = 1.0
return None
else:
trans.xalign = st
return 0
label start:
show logo base:
function slide_function
pause 1.0
repeat
Что оно значит, я не знаю, но в этом примере изображение слева движется направо.
Pause, then jump to the new value. If t == 1.0, t = 1.0. Otherwise, t' = 0.0.
linear
123
2018 Ren’Py
ease
Start slow, speed up, then slow down. t' = .5 - math.cos(math.pi * t) / 2.0
easein
easeout
Start slow, then speed up. t' = 1.0 - math.cos(t * math.pi / 2.0)
ease_back easeInOut_back
ease_bounce easeInOut_bounce
ease_circ easeInOut_circ
ease_cubic easeInOut_cubic
ease_elastic easeInOut_elastic
ease_expo easeInOut_expo
ease_quad easeInOut_quad
ease_quart easeInOut_quart
ease_quint easeInOut_quint
easein_back easeOut_back
easein_bounce easeOut_bounce
easein_circ easeOut_circ
easein_cubic easeOut_cubic
124
2018 Ren’Py
easein_elastic easeOut_elastic
easein_expo easeOut_expo
easein_quad easeOut_quad
easein_quart easeOut_quart
easein_quint easeOut_quint
easeout_back easeIn_back
easeout_bounce easeIn_bounce
easeout_circ easeIn_circ
easeout_cubic easeIn_cubic
easeout_elastic easeIn_elastic
easeout_expo easeIn_expo
easeout_quad easeIn_quad
easeout_quart easeIn_quart
easeout_quint easeIn_quint
New warpers can be defined using the renpy.atl_warper decorator, in a python early
block. It should be placed in a file that is parsed before any file that uses the warper.
This looks like:
@renpy.atl_warper
def linear(t):
return t
ПРИМЕР ИСПОЛЬЗОВАНИИ
init:
125
2018 Ren’Py
transform downup:
yanchor 1.0
yalign 0.0
transform updown:
yanchor 1.0
yalign 1.0
screen info_fade:
init:
transform fade_inout_2s:
xalign 0.5
yalign 0.5
alpha 0.08
easeout_back 2 alpha 0.9
pause 0
ease 2 alpha 0.0
label start:
scene bg room
"Ok, here we go."
show screen info_fade
126
2018 Ren’Py
pause 6
"That was nice."
pause
return
19)AROUND
Устанавливает центр координатной позиции на абсолютную позицию
show logo small:
anchor (0.5, 0.5)
around (640, 216)
20) ANGLE
Устанавливает значение угла в градусах
show logo small:
linear 1.0 angle 315
linear 1.0 angle 270
repeat
127
2018 Ren’Py
21) RADIUS
Определяет дистанцию от заданной позиции до центра координат
show logo small:
linear 1.0 radius 100
linear 1.0 radius 200
repeat
22)TILE
Клонирование объектов
show logo base:
xtile 3
ytile 2
Получаем 6 одинаковых изображений
23) PAN
Создать панораму
show bg panorama:
xpan 0
128
2018 Ren’Py
24) OFFSET
Прописывают в конце всех операторов, смещают изображение
вправо или вниз на то, сколько указали в их значении xoffset и yoffset
25) RANDMOTION
Что бы его вызвать, нужно немного поработать в питоне.
init:
python hide:
import random
args = [ ]
args.append(anim.State(i, None,
Position(xpos=random.randrange(-dist, dist),
ypos=random.randrange(-dist, dist),
xanchor='left', yanchor='top',
)))
129
2018 Ren’Py
if i == j:
continue
130
2018 Ren’Py
АВТОМАТИЧЕСКОЕ ОБЪЯВЛЕНИЕ
АНИМАЦИИ
(http://renpyfordummies.blogspot.ru/2015/06/init-python-def-ani-imgname-
frames.html)
init python:
"""
описание функции Ani:
автоматическое объявление картинки с анимацией,
например есть кадры "images/neko%s.png",
где %s - числа от 1 до 5, тогда объявляем анимацию так:
image neko = Ani("neko", 5, 0.5, reverse = False)
где:
img_name - имя файла без номера (например, "neko")
frames - количество кадров
delay - пауза между кадрами в секундах
loop - зациклить анимацию (по умолчанию включено)
reverse - нужно ли проигрывание анимации в обратную сторону
effect - эффект для смены кадров
start - с какой цифры начинать отсчет кадров
ext - расширение файлов (по умолчанию png)
"""
def Ani(img_name, frames, delay=.1, loop=True, reverse=True, effect=None,
start=1, ext="png", **properties):
args = []
for i in range(start, start + frames):
args.append(renpy.display.im.image(img_name + str(i) + "." + ext))
if reverse or loop or (i < start + frames - 1):
args.append(delay)
args.append(effect)
if reverse: # обратная анимация, если нужна
for i in range(start + frames - 2, start, -1):
args.append(renpy.display.im.image(img_name + str(i) + "." + ext))
131
2018 Ren’Py
init:
# эффект dissolve в полсекунды с учетом прозрачности
$ dd = Dissolve(.5, alpha=True)
# 5 кадров, смена раз в полсекунды и эффектом для смены кадров
# по умолчанию зациклена и с обратным ходом
image neko = Ani("neko", 5, .5, effect=dd)
label start:
show expression "bg_room.jpg"
show neko
pause
return
1) WITH DISSOLVE
label start:
scene logo with Dissolve(.5)
pause .5
132
2018 Ren’Py
2) WITH FADE
Вспышка, а потом переходит как dissolve к новой сцене. Им можно
создать эффект лампочки. Для этого вам нужно создать переменную с
указание ее цвета(в моем случае белый свет)
init:
133
2018 Ren’Py
И где то в проекте
label start:
scene komnata with flashbulb
И получаем эффект слеповой гранаты как в КонтрСтрайк.
Так же запомните что любой переход который вы создаете его
нужно прописывать в init
3) WITH PIXELLATE
Создает эффект перехода пикселей (Например, его часто используют
в космических новелках. Где герой получает изображение со спутника
и там изображение плавно появляется на экране)
134
2018 Ren’Py
4) WITH VPUNCH
Эффект встряски экрана (кувалдой по голове, сверху вниз)
5) WITH HPUNCH
Эффект встряски экрана (пощечина, слева на право)
6) WITH PAUSE(1)
Спросите, зачем нужна пауза? Допустим ваш герой провел обычный ничем не
примечательный день(и показываем сцены дом, школа, столовая, домой) если между
каждой сценой не ставить паузу, то программа эти сцены пропустит, так, что вы не
успеете ничего увидеть. Мгновенно практически. А если между каждой сценой поставить
паузу….то только щелчком мышки поменяются сцены. Или как сейчас тут показано через
1 секунду.
7)ЖЕСТКАЯ ПАУЗА
Так же есть жесткая пауза, например, вы нажали пропуск всех сцен, а вам нужно что
бы нельзя было пропустить нужную сцену, вот для этих целей и нужна жесткая пауза
scene bg1
$ renpy.pause(3.0, hard=True)
ПЕРЕХОДЫ MOVE
Move –это переход который меняет позиции изображения. Они
делятся на 3 типа – простые, moveout, movein
135
2018 Ren’Py
ПРОСТЫЕ ПЕРЕХОДЫ
Используется для перемещений по экрану изображений
Пример
show rish_1 at right
with move
show rish_1 at center
with move
Здесь мы видим, как rish_1 переходит справа в центр.
ПЕРЕХОД MOVEOUT
Используется, что бы скрыть изображение за экраном. Примеры
moveoutright – вправо
moveoutleft – влево
moveouttop - вверх
moveoutbotton – вниз
label start:
show pic
pause
hide pic at moveoutbotton
pause
Данные трансформации часто используют для плавного перехода
спрайта по экрану.
136
2018 Ren’Py
ПЕРЕХОД MOVEIN
Используют, для появлении изображения на экране
moveinright – вправо
moveinleft – влево
moveintop – вверх(ногами)
moveinbotton – вниз
label start:
show pic with moveintop
pause
ZOOMIN И ZOOMOUT
Показать и спрятать изображение масштабированием
hide eileen happy
with zoomout
CROPMOVE
Переход который похож на Move только старое изображение стоит на
месте, а новое плавно сверху на него наезжает.
with wiperight – на право
with wipeleft – на лево
with wipeup – вверх
with wipedown - вниз
137
2018 Ren’Py
ПЕРЕХОДЫ PUSHMOVE
Данный переход меняет сцену вытесняя старую. Как паровоз.
138
2018 Ren’Py
ПЕРЕХОДЫ КОТОРЫЕ
САМОСТОЯТЕЛЬНО
СОЗДАЮТСЯ(IMAGEDISSOLVE)
Для этих переходов используются другие изображения. В сообществе
ренпая я добавлял архив с кучей изображений для создания
эффектов начиная от телепорта….до перехода виде сердечек для
хэппи-эндов(около 200 картин)
https://vk.com/topic-7553243_31474171?post=8461
подбирайте именно подходящие для вас эффекты (Не забудьте
изображению-переходу дать такое же разрешение, как и ваш проект).
В ренпае уже существует 2 прописанных перехода
ЖАЛЮЗИ
with blinds
Пример:
scene black
with blinds
scene bg washington
show eileen happy
with blinds
КВАДРАТЫ
with squares
Пример:
scene black
139
2018 Ren’Py
with squares
scene bg washington
show eileen happy
with squares
И самостоятельно запишем спецэффект открытия глаз
140
2018 Ren’Py
ТЕЛЕПОРТ(ПОСТРОЧНОЕ ИЗЧЕЗНОВЛЕНИЕ)
Если нужно построчное исчезновение, как в телепорте то пишут
with teleport
141
2018 Ren’Py
ПЕРЕХОД ALPHADISSOLVE
"spotlight.png" частично прозрачное изображение
142
2018 Ren’Py
image alpha_control:
"spotlight.png"
parallel:
zoom 0
pause 2
parallel:
143
2018 Ren’Py
pause .5
repeat
label start:
scene bg washington
with alpha_example
144
2018 Ren’Py
init python:
def move_time(delay=.5, effects=["move", "ease"]):
effects = make_list(effects)
for i in effects:
define.move_transitions(i, delay)
# with diss
init:
diss = Dissolve(.1, alpha=True)
diss25 = Dissolve(.25, alpha=True)
145
2018 Ren’Py
ПРИМЕРЫ ИНТЕРЕСНЫХ
ТРАНСФОРМАЦИЙ(SPRITE).
label start:
scene black
show snowblossom
pause
146
2018 Ren’Py
block:
parallel:
alpha al
147
2018 Ren’Py
parallel:
rotate 0
repeat
init python:
pic = pic[0]
renpy.show(str(renpy.random.random()), what=At(renpy.random.choice(pic),
snowflakes))
label start:
pause
class StarField(object):
def __init__(self):
self.sm = SpriteManager(update=self.update)
148
2018 Ren’Py
self.stars = [ ]
d = Transform(«star.png», zoom=.02)
self.add(d, 20)
d = Transform(«star.png», zoom=.025)
self.add(d, 80)
d = Transform(«star.png», zoom=.05)
self.add(d, 160)
d = Transform(«star.png», zoom=.075)
self.add(d, 320)
d = Transform(«star.png», zoom=.1)
self.add(d, 640)
d = Transform(«star.png», zoom=.125)
self.add(d, 1280)
149
2018 Ren’Py
s = self.sm.create(d)
return 0
label start:
scene black
with wiperight
pause
# This spins the logo, while at the same time zooming it and decreasing the
# alpha.
150
2018 Ren’Py
st = st % 7.0
t.xpos = done
t.ypos = .5
t.yanchor = .5
return 0
label start:
e "The Transform function allows you to rotate, zoom, move, and adjust the alpha of a
displayable."
e "It does this under the control of a Python function, making it incredibly flexible at the cost of
some complexity."
hide eileen
with dissolve
e "Here's a simple example, showing how we can change an image as it moves around the
screen."
# this is the code for ball movement and so on. Only a very little bit of this
init python:
151
2018 Ren’Py
import math
class Ball(object):
self.x = x
self.y = y
MAX_SPEED = 150
# Rotation speed.
# This is called
"""
"""
DOUBLE_RADIUS = 75
d = math.hypot(x21, y21)
if d > DOUBLE_RADIUS:
return
152
2018 Ren’Py
return
if x21 == 0:
x21 = .00001
a = y21 / x21
p2.dx += dvx2
p2.dy += a * dvx2
p1.dx -= dvx2
p2.dy -= a * dvx2
# transforms.
global last_time
RADIUS = 75 / 2
LEFT = RADIUS
TOP = RADIUS
# The pilot is the first ball in our list, and he's the one
if last_time is None:
dt = 0
else:
dt = st - last_time
last_time = st
153
2018 Ren’Py
balls_collide(balls[i], balls[j])
for i in balls:
i.x += i.dx * dt
i.y += i.dy * dt
i.x = LEFT
i.dx = abs(i.dx)
i.x = RIGHT
i.dx = -abs(i.dx)
i.y = TOP
i.dy = abs(i.dy)
i.y = BOTTOM
i.dy = -abs(i.dy)
for i in balls:
i.transform.xpos = absolute(i.x)
i.transform.ypos = absolute(i.y)
i.transform.update()
return 0
label start:
154
2018 Ren’Py
e "If you use it to do a rotation, you can zoom or adjust alpha at no additional cost."
with dissolve
python:
last_time = None
balls = [
for i, b in enumerate(balls):
renpy.show("ball%d" % i, what=b.transform)
with dissolve
e "As the python functions get more complicated, more advanced behavior is possible."
python:
for i, b in enumerate(balls):
renpy.hide("ball%d" % i)
155
2018 Ren’Py
init -1 python:
# автоматическое объявление
config.automatic_images_minimum_components = 1
config.automatic_images = [' ', '_', '/']
config.automatic_images_strip = ["images"]
156
2018 Ren’Py
init:
image mmbg = BlinkinStars(30, "bg sky")
$ style.mm_root.background = "mmbg"
$ style.gm_root.background = "mmbg"
def repulsor_update(st):
px, py = repulsor_pos
157
2018 Ren’Py
# Move
i.x += distance * vx / vl
i.y += distance * vy / vl
if i.y < 2:
i.y = 2
return .01
label repulsor_demo:
python:
# Create a sprite manager.
repulsor = SpriteManager(update=repulsor_update, event=repulsor_event)
repulsor_sprites = [ ]
158
2018 Ren’Py
repulsor_pos = None
del smile
del i
"..."
hide repulsor
# Clean up.
python:
del repulsor
del repulsor_sprites
del repulsor_pos
label start:
call repulsor_demo
7)СИСЬКОТРЯС
159
2018 Ren’Py
# список героев, если есть грудь, то ее координаты относительно левого верхнего угла
спрайта
$ tits = [("laylastrip", (305, 263)), ("hitry", (280, 600)), ("tasha", (280, 555)), ("ani",(255, 466)),
"hanny", "tarisa", "layla", "eureka", "rian", "bron", "guardian", "kiron", "erion", "bertraed", "tryber",
"oper", "remdark"]
# список эмоций (если нужных спрайтов не будет, то они не будут создаваться)
$ emos = ["angry", "evil", "happy", "ok", "sad", "smile", "wat", "shame"]
# реалистичная анимация сиськотряса
transform boobs(name, boob_t = 2.0):
yanchor 0.0 yzoom 1.0
easeout (boob_t * .075) yzoom 1.05
easein (boob_t * .1) yzoom 0.95
easeout (boob_t * .125) yzoom 1.025
easein (boob_t * .125) yzoom 0.975
easeout (boob_t * .125) yzoom 1.01
easein (boob_t * .15) yzoom 0.990
easeout (boob_t * .15) yzoom 1.005
easein (boob_t * .15) yzoom 1.0
init 1999 python:
# автоматическое объявление персонажей
# с дополнительными «верхними половинками»,
# моргающие, с трясущимися сиськами (если это дамы)
# то есть у нас есть спрайты высотой 1700 (для того чтобы пробежаться взглядом по
всему телу)
# мы прикручиваем к ним моргающие головы с эмоциями и однократно трясущейся
грудью
# а еще обрезаем результат до высоты экрана (1080) - получаются обычные спрайты
for i in tits:
char_name = get_tname(i) # имя перса из списка
xy = get_tpos(i) # координаты сисек
w, h = (800, 1700) # стандартные размеры для всех спрайтов
tits_name = char_name + " tits" # сиськи имяперсонажа_tits.png
if xy[0] < 1 and xy[1] < 1: # если это мужик,
tits_name = "pixel" # то пусть трясет невидимыми сиськами
# перебираем все возможные эмоции
for emo in emos:
nemo = char_name + " " + emo # прикручиваем очередную эмоцию
img_head = nemo + " head" # картинка головы с открытыми глазами (во всю ширину
спрайта!)
img_blink = nemo + " blink" # голова с закрытыми глазами
# если одна из голов пустая, заменяем на другую
if not has_img(img_head):
img_head = "pixel"
if not has_img(img_blink):
img_blink = "pixel"
if img_blink == "pixel":
img_blink = img_head
if img_head == "pixel":
img_head = img_blink
if img_blink == "pixel":
img_blink = img_head
# если есть головы с нужной эмоцией, то создаем спрайты с ними
if img_head != "pixel" or img_blink != "pixel":
img_full = LiveComposite((w, h),
160
2018 Ren’Py
label start:
scene hitry ok:
zoom 1.15
pause
hitry_tits.png 200x200
161
2018 Ren’Py
hitry_ok_blink.png 800x540
162
2018 Ren’Py
hitry_ok_head.png 800x540
hitry_temp.png 800x1700
163
2018 Ren’Py
164
2018 Ren’Py
8) МАСКИРОВКА СНАЙПЕР
init python:
import math
class Appearing(renpy.Displayable):
# constructor.
super(Appearing, self).__init__(**kwargs)
# The child.
self.child = renpy.displayable(child)
# The distance at which the child will become fully opaque, and
self.opaque_distance = opaque_distance
self.transparent_distance = transparent_distance
self.alpha = 0.0
self.width = 0
self.height = 0
165
2018 Ren’Py
# child.
t = Transform(child=self.child, alpha=self.alpha)
return render
166
2018 Ren’Py
alpha = 1.0
alpha = 0.0
else:
if alpha != self.alpha:
self.alpha = alpha
renpy.redraw(self, 0)
def visit(self):
return [ self.child ]
screen alpha_magic:
xalign 0.5
yalign 0.5
label start:
9) ФОНАРИК
167
2018 Ren’Py
init python:
class Flashlight(renpy.Displayable):
def __init__(self):
super(Flashlight, self).__init__()
# This image should be twice the width and twice the height
# of the screen.
self.child = Image("flashlight.png")
def visit(self):
return [ self.child ]
screen flashlight_demo:
textbutton "continue" xpos 300 ypos 300 action Return()
add Flashlight()
label start:
$ mouse_visible = False
call screen flashlight_demo
168
2018 Ren’Py
Изображение
https://lemmasoft.renai.us/forums/download/file.php?
id=19774&mode=view
10) КОМПАС
Ссылка https://lemmasoft.renai.us/forums/viewtopic.php?f=51&t=23179
11) МЕТЕЛЬ
file star.rpy
init python:
"""
Based on:
3D Starfield Simulation
http://codeNtronix.com
http://twitter.com/codentronix
http://opensource.org/licenses/mit-license.php
"""
169
2018 Ren’Py
class ProjectionStarfield(renpy.Displayable):
"""
Fires out a displayable from the centre of the screen and outwards.
depth and perspective controls the starting position and how the displayables move.
"""
super(renpy.Displayable, self).__init__()
self.star_amount = star_amount
self.depth = depth
self.perspective = perspective
self.speed = speed
if image == None:
else:
self.image = Image(image)
self.stars = []
self.transforms = []
170
2018 Ren’Py
def start(self):
#Creates a list of starting positions for the starts, represented as: [x,y,z]
self.transforms = self._build_star_transforms(self.image)
"""Pre-calculate all the size/alpha transforms that are possible so they don't have to be
recreated
current_depth = float(self.depth)
all_depths = []
all_depths.append(current_depth)
current_depth -= self.speed
#Using Linear Interpolation, distant stars are smaller and darker than closer stars.
tr.reverse()
return tr
171
2018 Ren’Py
for x in range(amount):
for x in range(amount):
del self.stars[-1]
render = renpy.Render(0, 0)
star[2] -= self.speed
star[3] -= 1
#If the star exits the screen, move it to the back of the projection with random X and Y
coordinates.
if star[2] <= 0:
star[0] = randrange(-25,25)
star[1] = randrange(-25,25)
star[2] = self.depth
star[3] = len(self.transforms)-1
k = self.perspective / star[2]
x = int(star[0] * k + self.origin_x)
y = int(star[1] * k + self.origin_y)
172
2018 Ren’Py
render.blit(child_render,(x, y))
renpy.redraw(self, 0)
return render
file script.rpy
init:
#Create the starfield displayables. Optional keyword arguments can tweak the default
display.
$ n_starfield = ProjectionStarfield()
screen starfield:
add space
add n_starfield
screen starfield_with_image:
add space
add i_starfield
label start:
173
2018 Ren’Py
$n_starfield.start()
"Space."
$ n_starfield.add_stars(512)
$ n_starfield.subtract_stars(512)
$ i_starfield.start()
return
init:
transform transpa:
alpha 0.5
python hide:
174
2018 Ren’Py
import random
args = [ ]
args.append(anim.State(i, None,
Position(xpos=random.randrange(-dist, dist),
ypos=random.randrange(-dist, dist),
xanchor='left',
yanchor='top',
)))
if i == j:
continue
init python:
def double_vision_on(picture):
renpy.scene()
175
2018 Ren’Py
renpy.show(picture)
renpy.with_statement(dissolve)
def double_vision_off():
renpy.hide("blur_image")
renpy.with_statement(dissolve)
label start:
pause
http://ru.renpypedia.shoutwiki.com/wiki/%D0%92%D0%B7%D1%80%D1%8B%D0%B2_
%D1%87%D0%B0%D1%81%D1%82%D0%B8%D1%86_(Particle_Burst)
1) CROP
176
2018 Ren’Py
init:
label start:
show imy_ssilka
2) IM.COMPOSITE
177
2018 Ren’Py
init:
(0, 0),"logo.png",
(0, 50),"logo.png",
(0, 100),"logo.png")
3)LIVECOMPOSITE
Как и предыдущий оператор, только может использовать еще анимации
init:
178
2018 Ren’Py
4) IM.SCALE
init:
5) IM.FACTORSCALE
init:
179
2018 Ren’Py
6) IM.MAP
init:
180
2018 Ren’Py
7) IM.RECOLOR
Тоже самое что и im.Map но более эффективна при линейной обработке.
init:
8) MATRIXCOLOR
Позволяет изменять цвета и насыщеность
ТУСКЛЫЙ ОТТЕНОК
init:
181
2018 Ren’Py
ИНВЕРТИРОВАТЬ ОТТЕНОК
init:
[ -1, 0, 0, 0, 1,
0, -1, 0, 0, 1,
0, 0, -1, 0, 1,
0, 0, 0, 1, 0, ])
182
2018 Ren’Py
When the four components of the source color are R, G, B, and A, which
range from 0.0 to 1.0; the four components of the transformed color are R',
G', B', and A', with the same range; and the elements of the matrix are
named:
[ a, b, c, d, e,
f, g, h, i, j,
k, l, m, n, o,
p, q, r, s, t ]
R' = (a * R) + (b * G) + (c * B) + (d * A) + e
G' = (f * R) + (g * G) + (h * B) + (i * A) + j
B' = (k * R) + (l * G) + (m * B) + (n * A) + o
A' = (p * R) + (q * G) + (r * B) + (s * A) + t
The components of the transformed color are clamped to the range [0.0,
1.0].
im.matrix()
Constructs an im.matrix object from matrix. im.matrix objects support The operations supported
are matrix multiplication, scalar multiplication, element-wise addition, and element-wise
subtraction. These operations are invoked using the standard mathematical operators (*, *, +,
and -, respectively). If two im.matrix objects are multiplied, matrix multiplication is performed,
otherwise scalar multiplication is used.
im.matrix.brightness(b)
b
The amount of change in image brightness. This should be a number between -1 and 1, with -1
the darkest possible image and 1 the brightest.
im.matrix.colorize(black_color, white_color)
Returns an im.matrix that colorizes a black and white image. black_color and white_color are
Ren'Py style colors, so they may be specified as strings or tuples of (0-255) color values.
183
2018 Ren’Py
"bwlogo.png",
im.matrix.colorize("#f00", "#00f"))
im.matrix.contrast(c)
Returns an im.matrix that alters the contrast of an image. c should be greater than 0.0, with
values between 0.0 and 1.0 decreasing contrast, and values greater than 1.0 increasing
contrast.
im.matrix.desaturate()
Returns an im.matrix that desaturates the image (makes it grayscale). This is equivalent to
calling im.matrix.saturation(0).
im.matrix.hue(h)
Returns an im.matrix that rotates the hue by h degrees, while preserving luminosity.
im.matrix.identity()
Returns an identity matrix, one that does not change color or alpha.
im.matrix.invert()
Returns an im.matrix that inverts the red, green, and blue channels of the image without
changing the alpha channel.
im.matrix.opacity(o)
Returns an im.matrix that alters the opacity of an image. An o of 0.0 is fully transparent, while
1.0 is fully opaque.
Returns an im.matrix that alters the saturation of an image. The alpha channel is untouched.
level
The amount of saturation in the resulting image. 1.0 is the unaltered image, while 0.0 is
grayscale.
desat
This is a 3-element tuple that controls how much of the red, green, and blue channels will be
placed into all three channels of a fully desaturated image. The default is based on the
constants used for the luminance channel of an NTSC television signal. Since the human eye is
mostly sensitive to green, more of the green channel is kept then the other two channels.
im.matrix.tint(r, g, b)
Returns an im.matrix that tints an image, without changing the alpha channel. r, g, and b should
be numbers between 0 and 1, and control what fraction of the given channel is placed into the
final image. (For example, if r is .5, and the value of the red channel is 100, the transformed
color will have a red value of 50.)
184
2018 Ren’Py
9) IM.GRAYSCALE
init:
185
2018 Ren’Py
10) IM.SEPIA
init:
186
2018 Ren’Py
11) IM.ALPHA
init:
Эффект призрака
init:
# сам эффект
187
2018 Ren’Py
contains:
img_name
alpha 1.0
contains:
img_name
contains:
img_name
contains:
img_name
contains:
img_name
label start:
scene bg
# пример применения
pause
return
188
2018 Ren’Py
12) IM.FLIP
init:
13) TEXT
189
2018 Ren’Py
190
2018 Ren’Py
return
ВИЗУАЛЬНЫЙ ЗАПОЛНИТЕЛЬ
191
2018 Ren’Py
base:
192
2018 Ren’Py
flip – вертикал
ДИНАМИЧЕСКИЙ ФОН
(Руслан Небыков)
Работая над новеллой «Сателлит», я столкнулся с такой проблемой. У
меня был динамический фон – плывущие по небу облака и
движущийся немного с другой скоростью пейзаж. Всё было
замечательно, пока по экрану не начали двигаться спрайты. По
завершении движения или при уничтожении спрайта Renpy
перерисовывает фон. А значит, анимация запускается заново.
Происходит рывок. Допустим тучки прошли только треть пути, и тут их
возвращают на исходную. Выглядит это очень некрасиво. Но чтобы
фон не перерисовывался, его можно засунуть в экран, который будет
выводиться прямо поверх фона, но под спрайтами. Как это сделать,
видно из кода ниже.
(http://renpyfordummies.blogspot.ru/2016/02/blog-post_24.html)
init -3 python:
# окно игры в центре экрана
import os
os.environ['SDL_VIDEO_CENTERED'] = '1'
# автоматическое объявление изображений
config.automatic_images_minimum_components = 1
config.automatic_images = [' ', '_', '/']
config.automatic_images_strip = ['images']
init:
# трансформация для перемещения фона
transform _moveleft(delay=7.5):
xalign 1.0
linear delay xalign 0.0
repeat
# экран с фоном
screen scr_bg:
193
2018 Ren’Py
label start:
scene black
# показать фон
show screen scr_bg(_layer="master")
with dissolve
# движение спрайта
show mtt at Truecenter with easeinright
pause .25
hide mtt with easeoutleft
# спрятать фон
$ renpy.hide_screen("scr_bg", layer="master")
with dissolve
return
НЕУБИРАЮЩИЙСЯ ПО HIDEINTERFACE()
ЭКРАН
Допустим, мы захотели как-то оформить интерфейс игры. Добавить экран с какими-то
элементами. Но при нажатии на кнопку 'h' все экраны прячутся, в том числе и тот, что
прятаться не должен. Чтобы этого избежать, можно размещать неубирающийся экран на
отдельном слое.
(http://renpyfordummies.blogspot.ru/2016/02/hideinterface.html)
init -1:
# список слоев. если наш tvframe поставить в другое место,
# то не сработает распознавание экрана настроек.
# а так наш экран не будет исчезать при нажатии 'h'
$ config.layers = ["master", "transient", "tvframe", "screens", "overlay"]
194
2018 Ren’Py
screen frm:
# выводится, если это игра, но не экран настроек
if not ("preferences" in renpy.current_screen().screen_name):
add "bg frame"
(http://renpyfordummies.blogspot.ru/2016/02/blog-post.html)
195
2018 Ren’Py
196
2018 Ren’Py
label start:
scene black
# отображаем (параметры можно не указывать)
$ _scroll("sky", Dissolve(2.0), 15)
pause # наслаждаемся облаками
# а теперь прячем наши бегущие картинки
$ _hide("sky", Dissolve(2.0))
pause .5
return
РЕЖИМ NVL
Данный режим выставляет на весь экран текст, а не выставляет его в
нижней части экрана на специальную рамку(речь идет о режиме ADV)
Самый простой способ выставить его – прописать в персонаже
define nvle = Character(_("Eileen"), color="#c8ffc8", kind=nvl)
define misli = Character(None, color="#c8ffc8", kind=nvl)
label start:
misli "Мысли"
mvle "Диалог"
nvl clear
197
2018 Ren’Py
МЕНЮ В NVL
Так же в этом режиме можно использовать меню выбора, для этого
вам потребуется прописать
init -1 python hide:
define menu = nvl_menu
label start:
menu:
nvle "NVL-mode"
"Yes.":
nvl clear
nvle "Good!"
"No.":
nvl clear
nvle "Well"
init python:
config.nvl_paged_rollback = True
198
2018 Ren’Py
199
2018 Ren’Py
1) ИСТИННЫЙ
Открываете сценарий gui.rpy и находите такую строку
2) КОСТЫЛЬНЫЙ
200
2018 Ren’Py
define sh = Character('Shino',
color="9966cc",
window_background = Frame("textbox3.png", 0, 0), #Your custom textbox.
window_left_margin = 320,
window_right_margin = 10,
window_top_margin = 70,
window_bottom_margin = 500,
window_left_padding = 60,
window_right_padding = 10,
window_top_padding = 70,
window_bottom_padding = 75,
ctc="ctc_blink")
201
2018 Ren’Py
define config.nvl_list_length = 6
РЕЖИМ ADV
Данный режим выставляет текст диалога внизу экрана, где видно имя персонажа,
диалоговое окно и само изображение персонажа в диалоговом окне.
## Диалог
############################################################
######
## Эти переменные контролируют, как диалог появляется на
отдельной строчке.
202
2018 Ren’Py
## Экран разговора
############################################################
#
##
## Экран разговора используется для показа диалога игроку. Он
использует два
## параметра — who и what — что, соответственно, имя говорящего
персонажа и
## показываемый текст. (Параметр who может быть None, если имя не
задано.)
##
## Этот экран должен создать текст с id "what", чтобы Ren'Py могла
показать
## текст. Здесь также можно создать наложения с id "who" и id
"window", чтобы
## применить к ним настройки стиля.
##
## https://www.renpy.org/doc/html/screen_special.html#say
203
2018 Ren’Py
init:
config.hard_rollback_limit = 0
label start:
….
Что бы на 10 откатов назад, то цифру 0 меняют на 10
label v1:
$ renpy.fix_rollback() ###Откат работает, но вариант выбора нельзя
поменять
"Текст"
label v2:
$ renpy.fix_rollback() ###Откат работает, но вариант выбора нельзя
поменять
"Текст"
205
2018 Ren’Py
или сокращенно
queue music [ "a.ogg", "b.ogg" ]
$ renpy.music.set_volume(0.2)
Я все ближе к комнате.
$ renpy.music.set_volume(0.5)
Практически открываю дверь.
$ renpy.music.set_volume(1.0)
Я в комнате.
206
2018 Ren’Py
voice "e01.ogg"
imya_silka "текст."
init:
$ playlist = ["song1.mp3", "song2.mp3", "song3.mp3", "song4.mp3",
"song5.mp3"]
$ renpy.random.shuffle(playlist)
label start:
play music playlist fadeout 1.0 fadein 1.0
207
2018 Ren’Py
Собственно, всё.
Если хочется, чтобы в меню играло несколько мелодий по порядку, то
пишем:
define config.main_menu_music = ["music1.mp3", "music2.mp3",
"music3.mp3", "music4.mp3"]
или что бы они все перемешались
define config.main_menu_music = renpy.random.shuffle(["music1.mp3",
"music2.mp3", "music3.mp3", "music4.mp3"] )
Однако, в этом случае мелодия будет играть и после нажатия кнопки
старт.
Чтобы отключить музыку, после начала игры (нажатием кнопки start)
находим в сценарии script.rpy строку label start: и под ней
дописываем, не забывая про четыре пробела:
208
2018 Ren’Py
209
2018 Ren’Py
И примеры в сценарии
play music "<from 5 to 15.5>waves.opus"
АЛЬТЕРНАТИВА
screen my_music_scr(t, melody):
label start:
"?"
Другое действие
210
2018 Ren’Py
init python:
def mplay(mname, fin=0, fout=0):
renpy.play("music/" + mname + ".mp3", channel="music", loop=True, fadein=fin,
fadeout=fout)
def splay(mname, fin=0, fout=0):
renpy.play("sound/" + mname + ".mp3", channel="sound", loop=False, fadein=fin,
fadeout=fout)
label start:
$ mplay("music1")###музыка с именем music1.mp3
$ splay("ku_ku")###звук с именем ku_ku.mp3
init python:
211
2018 Ren’Py
init python:
212
2018 Ren’Py
213
2018 Ren’Py
init:
### фильтры для освещения
image morning = "#8404"
image day = "#0000"
image evening = "#0484"
image night = "#000b"
init python:
# узнать громкость и перевести ее в целочисленные проценты
def getV(mixer):
return (int)(_preferences.get_volume(mixer)*100)
def __call__(self):
v = _preferences.get_volume(self.mixer) + self.value
if v > 1.0:
v = 1.0
214
2018 Ren’Py
if v < 0.0:
v = 0.0
_preferences.set_volume(self.mixer, v)
def get_selected(self):
return _preferences.get_volume(self.mixer) == self.value
215
2018 Ren’Py
init python:
class __MusicInteract(renpy.Displayable):
__author__ = "Vladya"
super(__MusicInteract, self).__init__()
self.channel = channel
self.music_data = {
"args": [filenames, channel] + list(music_ar),
"kwargs": music_kw
}
self.__start_interact = False
def start_play(self):
renpy.music.play(
*self.music_data["args"],
**self.music_data["kwargs"]
)
self.__start_interact = True
return ui.interact()
renpy.redraw(self, 0)
return renpy.Render(1, 1)
label start:
$ play_interact("sound/file123.ogg", loop=False)
216
2018 Ren’Py
"Конец песни."
return
SPLASHSCREEN
Что это такое? Это экран, что появляется во время запуска
приложения.
Существуют 2 типа splashscreen
МЕТКА SPLASHSCREEN
217
2018 Ren’Py
….centered "{size=+10}САМИЗДАТ{/size}\n\n\n\n\nЛитературно-
публицистический журнал\n\n\n\n {size=-5}
{a=http://samlib.ru}http://samlib.ru{/a}{/size}"
….centered "Посетите нашу группу {a=http://vk.com/renpy}Ren'Py на
vk.com{/a}"
….return
laber start:
….
Обязательно в конце ставьте return иначе игра начнется без
главного меню. Сохраните и запустите ваш проект.
label splashscreen:
if persistent.one:
scene black
menu:
"Да":
218
2018 Ren’Py
jump afterintro
"Нет":
pass
scene black
centered "Внимание\n
centered "{size=+10}САМИЗДАТ{/size}\n\n\n\n\nЛитературно-публицистический
журнал\n\n\n\n {size=-5}{a=http://samlib.ru}http://samlib.ru{/a}{/size}"
$ persistent.one = True
label afterintro:
pass
return
laber start:
……..
219
2018 Ren’Py
label splashscreen:
if not persistent.one:
scene black
menu:
"Да":
$ persistent.one = True
pass
"Нет":
$ renpy.quit()
pass
return
label start:
ИЗОБРАЖЕНИЕ SPLASHSCREEN
220
2018 Ren’Py
ЭКРАНЫ
label start:
call screen simple_screen
pause
221
2018 Ren’Py
222
2018 Ren’Py
ЭКРАН С 3 ПАРАМЕТРАМИ
Вот еще 1 пример экрана, который берет сразу 3 параметра
init:
$ message = "Привет мир"
screen parameter_screen(message, okay=Return(True),
cancel=Return(False)):
frame:
xalign 0.5 ypos 50
vbox:
text "[message!t]"
textbutton _("Okay"):
action okay
textbutton _("Cancel"):
action cancel
label start:
show screen parameter_screen(_("Привет."), cancel=Notify(_("Ты не
можешь отменить")))
pause
223
2018 Ren’Py
screen modal_example():
modal True
frame:
action Hide("modal_example")
label start:
pause
224
2018 Ren’Py
2)ZORDER
label start:
show screen zorder_100_screen
pause
Стандартный экран имеет значение 0
3)STYLE_PREFIX
225
2018 Ren’Py
color "#ffc0c0"
label start:
show screen style_prefix_screen
pause
4) TAG MENU
PYTHON В ЭКРАНАХ
Операторы питона в экранах работают точно так же как и в обычном
скрипте.
226
2018 Ren’Py
label start:
show screen single_python_screen
show screen block_python_screen
pause
227
2018 Ren’Py
ОПЕРАТОРЕ DEFAULT
В операторе default можно установить первоначальное значение
переменной экрана при его запуске. Это значение может быть
изменено через SetScreenVariable и ToggleScreenVariable
Пример
screen default_screen():
default n = 0
frame:
xalign 0.5 ypos 50
vbox:
text "n = [n]"
textbutton _("Увеличить значение") action SetScreenVariable("n",
n + 1)
label start:
show screen default_screen
228
2018 Ren’Py
vbox:
if n > 2:
text "n = [n]" color "#cfc"
else:
text "n = [n]" color "#fcc"
textbutton _("Увеличить") action SetScreenVariable("n", n + 1)
label start:
show screen if_screen
pause
ОПЕРАТОР FOR
Есть в переменных еще оператор for. Он берет список, каждое
значение в списке запускает в блоке action.
screen for_screen():
$ landings = [ _("Earth"), _("Moon"), _("Mars") ]
frame:
xalign 0.5 ypos 50
vbox:
for i in landings:
textbutton "[i!t]" action Return(i)
229
2018 Ren’Py
label start:
show screen for_screen
pause
С Frame
230
2018 Ren’Py
231
2018 Ren’Py
screen add_image_example():
add "logo base"
Так же можно в нем прописать и анимации, со всеми объектами и
трансформациями.
screen add_at_transform_example():
add "logo base" at unrotate
label start:
show screen add_at_transform_example
232
2018 Ren’Py
screen main_menu():
style_prefix "main_menu"
add gui.main_menu_background
233
2018 Ren’Py
vbox:
style_prefix "navigation"
xpos gui.navigation_xpos
yalign 0.5
spacing gui.navigation_spacing
if main_menu:
ОПЕРАТОР TEXT
Данный оператор прописывает текст на экране.
screen text_example():
frame:
234
2018 Ren’Py
frame:
xalign 0.5 ypos 50
text _("Ответ: [answer].")
label start:
show screen text_interpolation_example
pause
235
2018 Ren’Py
frame:
…………….
ОПЕРАТОР ON
Данный оператор запускает автоматически событие при его вызове. В
нижнем примере будет 2 события: событие show (экран впервые
показывается) и событие hide(экран убирается)
screen on_screen():
on "show" action Notify(_("Появился экран"))
on "hide" action Notify(_("Экран убрали"))
236
2018 Ren’Py
label start:
schow screen on_screen
"Привет"
hide screen on_screen
"Пока"
Как видим, данный экран с текстом уведомления Notify и через
несколько секунд текст исчезает.
ОПЕРАТОР KEY
Данный оператор позволяет вызывать события нажатием клавиши на
клавиатуре.
screen on_key_screen():
frame:
xalign 0.5 ypos 50
text _("Нажмите на англ букву'a'.")
237
2018 Ren’Py
label start:
show screen on_key_screen
Питон очень чувствителен к тому, какой раскладкой клавиатуры вы
нажали и не активирована ли Caps Lock . Например, в выше
написанном примере буква а, будет активна, только на английской
раскладке при отключенном Caps Lock. Что бы она правильно
работала на русской (или китайской и т.д.) клавише нам потребуется
прописать все варианты значений (Заглавную, маленькую, и на другом
языке).
screen on_key_screen():
frame:
xalign 0.5 ypos 50
text _("Нажмите на англ букву'a'.")
key "a" action Notify(_("Вы нажали на А"))
key "A" action Notify(_("Вы нажали на А"))
key "Ф" action Notify(_("Вы нажали на А"))
key "ф" action Notify(_("Вы нажали на А"))
label start:
show screen on_key_screen
238
2018 Ren’Py
УПРАВЛЯЕМ ШТРУДЕЛЕМ
init:
$ ax, ay = (.5, .5)
$ aplus = .01
transform axy(x, y):
align(x, y)
image pers = Text("{size=256}@")
screen test:
key "focus_left" action SetVariable("ax", ax - aplus)
key "focus_right" action SetVariable("ax", ax + aplus)
key "focus_up" action SetVariable("ay", ay - aplus)
key "focus_down" action SetVariable("ay", ay + aplus)
add "pers" at axy(ax, ay)
label start:
centered "Жми кнопки стрелок для управления штруделем.{w=2.0}
{nw}"
show screen test
pause
return
КОЛЕСИКО МЫШКИ
screen my_keys:
key "rollback" action Show("название_экрана") # заменит действие
"перемотка назад" на показ экрана (затронет колесико мыши, кнопку
PgUp и кнопку джойстика)
key "mousedown_5" action Hide("название_экрана") # установит
действие для прокрутки колесика вперед
label start:
239
2018 Ren’Py
screen my_message():
text message
key "p" action Function(next_letter)
# rest of keys
label start:
call screen my_message
"Вы создали новую игру Ren'Py."
240
2018 Ren’Py
241
2018 Ren’Py
242
2018 Ren’Py
screen grid_example():
frame:
xalign 0.5 ypos 50
grid 3 2:
spacing 10
text "1"
text "2"
text "3"
text "4"
text "5"
null
label start:
show screen grid_example
243
2018 Ren’Py
244
2018 Ren’Py
label start:
show screen grid_transpose_example
245
2018 Ren’Py
246
2018 Ren’Py
frame: -рамка
247
2018 Ren’Py
248
2018 Ren’Py
249
2018 Ren’Py
zorder 100
style_prefix "note"
frame at note_appear:
text "[message!tq]"
transform note_appear:
on show:
alpha 0
linear .25 alpha 1.0
on hide:
linear .5 alpha 0.0
250
2018 Ren’Py
style notify_frame:
xalign 0.5 ypos 0.82 xpos 0.97
background None #Frame("gui/notify.png", gui.notify_frame_borders,
tile=gui.frame_tile)
style note_text:
properties gui.text_properties("note")
color "#fff"
size 40
font "fonts/myfont.ttf"
И где то
init:
def show_note(text):
renpy.show_screen("note", message=text)
screen button2:
frame:
align 0.5
251
2018 Ren’Py
screen myScreen(*variants):
default defPic = Null()
default isShow = False
showif isShow:
add At(defPic, atlShowTrans)
hbox:
align (.5, .75)
spacing 300
for txt, pic, lab in variants:
textbutton txt:
252
2018 Ren’Py
text_size 100
action Jump(lab)
hovered (
SetScreenVariable("defPic", pic),
SetScreenVariable("isShow", True)
)
unhovered SetScreenVariable("isShow", False)
init python:
renpy.show_screen(name, **kw)
renpy.transition(trans)
try:
result = ui.interact(
mouse="screen",
type="screen",
roll_forward=renpy.roll_forward_info()
253
2018 Ren’Py
)
except _exceptions as exc:
result = exc
renpy.hide_screen(name)
renpy.transition(trans)
renpy.exports.checkpoint(result)
if isinstance(result, _exceptions):
raise result
return result
screen testScreen:
textbutton u"Тестовый элемент" action Jump("testLabel")
label start:
scene black with None
$ _call_screen("testScreen", dissolve)
return
label testLabel:
"Следующий лейбл."
return
254
2018 Ren’Py
unhovered
Действие когда с кнопки убрали мышь
selected
Выражение, которое определяет, нажата ли кнопка или нет.
sensitive
Выражение, которое определяет, чувствительна ли кнопка или нет.
keysym
Строка, дающая keysym описание клавиши на клавиатуре, которая,
когда нажато, вызывает действие этой кнопки.
alternate_keysym
Строка, дающая keysym описание клавиши на клавиатуре, которая,
когда нажато, вызывает альтернативное действие этой кнопки.
255
2018 Ren’Py
ACTION ****
Список действий
Jump(LABEL) - прыжок к метке
Call(LABEL, FROM_CURRENT=FALSE) - вызов метки
Show(SCREEN, TRANSITION=NONE, *ARGS, **KWARGS) -вызвать
Hide(SCREEN, TRANSITION=NONE) – убрать
NullAction(*ARGS, **KWARGS) – ничего не делать
Return(VALUE=NONE)- возвратиться назад, True и False
ShowTransient(SCREEN, *ARGS, **KWARGS) - Показывает
переходный экран. Переходный экран будет скрыт, когда текущее
взаимодействие завершит.
ДЕЙСТВИЯ ДАННЫХ
256
2018 Ren’Py
True_value
Если не Ни один, то это - истинное значение, которое мы
используем.
False_value
Если не Ни один, то это - ложное значение, которое мы
используем.
257
2018 Ren’Py
MENU ACTIONS
Эти действия вызывают меню или прежде всего полезны как в основном или игровом
меню.
FILE ACTIONS
Эти действия применяются в сохранениях, загрузках и удалении файлов.
258
2018 Ren’Py
AUDIO ACTIONS
PauseAudio(channel, value=True)- Устанавливает паузу для канала.
VOICE ACTIONS
PlayCharacterVoice(VOICE_TAG, SAMPLE, SELECTED=FALSE)- Это играет образец на
голосовом канале, как будто сказанный характером с voice_tag.
SAMPLE -Полный путь к звуковому файлу. Никакая связанная с голосом обработка этого
файла не сделана.
259
2018 Ren’Py
OTHER ACTIONS
Confirm(prompt, yes, no=None, confirm_selected=False)- Предлагает пользователю
подтверждение действия. Если пользователь щелкает да, действие выполняется. Иначе
никакое действие не выполняется.
With(TRANSITION)- переход
260
2018 Ren’Py
Большая часть функций, которые чаще всего используют при нажатии, я привел,
остальные смотрите в офф документации ренпая.
IMAGEBUTTON
Имеет много общего с текстовой кнопкой, но и имеются и различия.
label start:
call screen gui_game_menu
screen imagebutton_example():
frame:
xalign 0.5 ypos 50
imagebutton:
idle "logo bw"
hover "logo base"
261
2018 Ren’Py
action Jump('ddde')
label start:
call screen imagebutton_example
262
2018 Ren’Py
screen button_inline_style_example():
frame:
xalign 0.5 ypos 50
textbutton _("Кликните на меня."):
idle_background Frame("button glossy idle", 12, 12)
hover_background Frame("button glossy hover", 12, 12)
xpadding 20
ypadding 10
xmargin 5
ymargin 5
hover_sound "pong_beep.opus"
text_idle_color "#c0c0c0"
text_hover_color "#ffffff"
action Notify(_("Вы нажали на кнопку."))
label start:
call screen button_inline_style_example
263
2018 Ren’Py
style button:
background "#006"
insensitive_background "#444"
hover_background "#00a"
264
2018 Ren’Py
265
2018 Ren’Py
on appear:
alpha 1.
on show:
linear .01 alpha .0
linear t alpha 1.
on hide:
linear t alpha .0
screen myScreen(*variants):
default defPic = Null()
default isShow = False
showif isShow:
add At(defPic, atlShowTrans)
hbox:
align (.5, .75)
spacing 300
for txt, pic, lab in variants:
textbutton txt:
text_size 100
action Jump(lab)
hovered (
SetScreenVariable("defPic", pic),
SetScreenVariable("isShow", True)
)
unhovered SetScreenVariable("isShow", False)
266
2018 Ren’Py
label start:
call screen myScreen((_("Затемнить"), Solid("#000"), "metka1"),
("Осветлить", Solid("#fff"), "metka2"))
label metka1:
pass
label metka2:
pass
return
1) Их видно на экране
По крайней мере, большинство новелл, где их использовали, мне они
казались чужеродными, т.к. они не полностью сливались с фоном.
2)Занимает память.
Когда вы прописываете 1 кнопку, в ренпае создается сколько то там кб
(вроде 300кб точно не помню) системой, что не является плюсом на мобил
устройства.
Но у кнопок так же есть ряд плюсов, если сравнивать с другими видами граф
карт.
1)Простота
Что бы написать 10 кнопок разбросанных по всему экрану(не столбцами) у
многих займет ну максимум час(где пол часа – спор с командой как лучше
расположить кнопки для лучшего дизайна).
В imagemap(hotspot) что бы рассчитать угол координаты, размер кнопки для
1 кнопки, может занять ну минут 15, а представьте если их 10 шт… плюс
редактирования командой координат(опять дизайн наше все). и опять
переставлять и вычислять все это сколько времени уйдет.
И таким образом на imagemap(hotspot) у вас может уйти спокойно пол
дня(образно)
267
2018 Ren’Py
2)Любая форма
Вы можете сделать круглую кнопку, зигзагообразная и т.д. а в
imagemap(hotspot) вы можете сделать активной зоной только квадратный
участок.
ГРАФИЧЕСКАЯ КАРТА
IMAGEMAP(HOTSPOT)
Графическая карта отличается от кнопки тем, что само изображение
является одновременно фоном и кнопкой. Благодаря этому у
imagemap кнопки полностью сливаются с фоном. Не смотря на
минусы(время на расчет координат, квадратная зона выделения…)
это все компенсируется тем что кнопки сливаются с фоном(ибо
красиво, когда все гармонично и не чужеродно смотрится).
Как вообще выглядит граф карта? Имеет много общего с imagebutton,
в плане выделения. idle_ и hover_. Но имеются и расхождения.
imagemap:
hotspot (970, 140, 270, 85)
Разберем что это значит.
imagemap: - объявляем графическую карту в которой прописываем
координаты горячих кнопок
hotspot (970, 140, 270, 85) - горячая кнопка, которая при наведении на
эту область будет активировано действие/наведение.
Теперь разберем подробней как определять числа в скобках
Первые 2 числа это верхний левый угол горячей кнопки.(х и у)
Последние 2 числа это координаты области действия кнопки(х и у)
Пример как выглядит все это в фотошоппе
268
2018 Ren’Py
1 и 2 цифра
269
2018 Ren’Py
270
2018 Ren’Py
Далее нам для данного главного меню, придется почти все уже
прописанные значения экранов удалить с 243 строки(после значения
screen choice(items):) по 1135(до значения screen confirm(message,
yes_action, no_action):)
271
2018 Ren’Py
272
2018 Ren’Py
273
2018 Ren’Py
274
2018 Ren’Py
275
2018 Ren’Py
276
2018 Ren’Py
277
2018 Ren’Py
278
2018 Ren’Py
imagemap_config_hover
imagemap_config_idle
279
2018 Ren’Py
imagemap_config_selected_hover
imagemap_config_selected_idle
280
2018 Ren’Py
tooltip_config_all
tooltip_config_disable_transition
tooltip_config_enable_transition
tooltip_config_fullscreen
tooltip_config_go_skip
tooltip_config_seen
tooltip_config_skipping
281
2018 Ren’Py
tooltip_config_stop_skip
tooltip_config_windowed
282
2018 Ren’Py
my_picture="gui/tooltip_config_fullscreen.png", my_tt_xpos=46,
my_tt_ypos=518) ] unhovered [Hide("gui_tooltip")]
hotspot (645, 252, 96, 96) action Preference('transitions', 'none')
hovered [Show("gui_tooltip",
my_picture="gui/tooltip_config_disable_transition.png", my_tt_xpos=46,
my_tt_ypos=518) ] unhovered [Hide("gui_tooltip")]
hotspot (758, 252, 96, 96) action Preference('transitions', 'all') hovered
[Show("gui_tooltip", my_picture="gui/tooltip_config_enable_transition.png",
my_tt_xpos=46, my_tt_ypos=518) ] unhovered [Hide("gui_tooltip")]
283
2018 Ren’Py
284
2018 Ren’Py
285
2018 Ren’Py
imagemap_load_ground
imagemap_load_hover
286
2018 Ren’Py
imagemap_load_idle
imagemap_load_selected_hover
287
2018 Ren’Py
imagemap_load_selected_idle
imagemap_save_ground
288
2018 Ren’Py
imagemap_save_hover
imagemap_save_idle
289
2018 Ren’Py
imagemap_save_selected_hover
290
2018 Ren’Py
imagemap_save_selected_idle
tooltip_geme_menu_load
291
2018 Ren’Py
tooltip_geme_menu_main
tooltip_geme_menu_quit
tooltip_geme_menu_return
tooltip_geme_menu_save
screen save:
tag menu
imagemap:
ground 'gui/imagemap_save_ground.jpg'
idle 'gui/imagemap_save_idle.png'
hover 'gui/imagemap_save_hover.png'
selected_idle 'gui/imagemap_save_selected_idle.png'
selected_hover 'gui/imagemap_save_selected_hover.png'
292
2018 Ren’Py
293
2018 Ren’Py
И экран загрузки
screen load:
tag menu
imagemap:
ground 'gui/imagemap_load_ground.jpg'
idle 'gui/imagemap_load_idle.png'
hover 'gui/imagemap_load_hover.png'
selected_idle 'gui/imagemap_load_selected_idle.png'
selected_hover 'gui/imagemap_load_selected_hover.png'
294
2018 Ren’Py
ОБЬЕКТЫ-ПОЛОСКИ (BAR )
Обьекты bar – гибкие полоски , которые отображают любое значение в
виде полосок.
295
2018 Ren’Py
296
2018 Ren’Py
frame:
xalign 0.5 ypos 50
xsize 500
vbox:
spacing 10
label start:
call screen bars_example
297
2018 Ren’Py
frame:
xalign 0.5 ypos 50
ysize 300
hbox:
spacing 10
298
2018 Ren’Py
299
2018 Ren’Py
300
2018 Ren’Py
301
2018 Ren’Py
302
2018 Ren’Py
theme.tv(
## Theme: TV
## Color scheme: First Valentines
303
2018 Ren’Py
disabled = "#F8F2D0",
## And we're done with the theme. The theme will customize
304
2018 Ren’Py
style.pref_vbox.xfill = True
style.pref_button.size_group = "pref"
style.pref_button.xalign = 1.0
style.pref_slider.xmaximum = 192
style.pref_slider.xalign = 1.0
style.soundtest_button.xalign = 1.0
305
2018 Ren’Py
ДЕЙСТВИЯ БАРА
пример про что я имею в виду
bar:
at transform_ese_left
xmaximum 130
value red_hood_hp
306
2018 Ren’Py
range red_hood_max_hp
307
2018 Ren’Py
308
2018 Ren’Py
1) style.imya.bar_vertical = True
Если значение True, то панель имеет вертикальную ориентацию. Если False, он имеет
горизонтальную ориентацию.
2) style.imya.bar_invert = True
3) ) style.imya.bar_resizing = True
Если True, то размеры сторон бруска. Если False, мы представляем стороны бара в
полном размере, а затем обрезать их.
4) style.imya.left_gutter = число
5) style.imya.right_gutter = число
6) style.imya.top_gutter = число
7) style.imya.bottom_gutter = число
309
2018 Ren’Py
thumb - это бегунок в центре панели, нажав, на которую пользователь может перетащить.
Если нет ни у кого, это визуализуемым, поверх разрыва между сторонами в баре
Если нет ни у кого, это визуализуемым, поверх разрыва между сторонами в баре.
Стиль мыши, используемый при фокусировке кнопки. Это должен быть один из стилей из
config.mouse
style.imya.unscrollable = "insensitive"
style.imya.unscrollable = "hide"
310
2018 Ren’Py
311
2018 Ren’Py
https://lemmasoft.renai.us/forums/viewtopic.php?f=8&t=27159&p=328819#p328841
DEFAULT
312
2018 Ren’Py
if club:
textbutton "Выбрать" action Return(club)
VIEWPORT
Порт просмотра – применяют, когда нам нужно показать что то, что
больше экрана.
Вот простой пример такого порта
screen viewport_screen():
313
2018 Ren’Py
viewport:
xalign 0.5 ypos 50 xysize (700, 300)
draggable True
mousewheel True
arrowkeys True
add "bg band"
Рассмотрим что тут записано
screen viewport_screen(): -имя экрана в котором мы пишем
xalign 0.5 ypos 50 – место положение на экране
xysize (700, 300) – ограничиваем размер отбражаемого окна, иначе на
весь экран получим картинку
draggable True – нажав на экран порта просмотра, мы переносимся по
экрану
mousewheel True – вертикальная прокрутка мыши
arrowkeys True - прокручивать порт просмотра с помощью клавиш со
стрелками и контроллера d-pad.
add "bg band" – изображение которое будем просматривать
viewport:
xalign 0.5 ypos 50 xysize (700, 300)
314
2018 Ren’Py
315
2018 Ren’Py
screen scrollbar_viewport_screen():
viewport:
xalign 0.5 ypos 50 xysize (700, 300)
scrollbars "both"
spacing 5 ###расстояние от порта до края изображен
draggable True
mousewheel True
arrowkeys True
2) ГОРИЗОНТАЛЬНЫЕ ПОЛОСЫ
(SCROLLBARS "HORIZONTAL")
316
2018 Ren’Py
screen child_size_viewport_screen():
viewport:
xalign 0.5 ypos 50 xysize (700, 300)
child_size (1000, None)
scrollbars "horizontal"
spacing 5
draggable True
mousewheel True
arrowkeys True
add "#000c"
text _("Этот текст больше размера экрана") size 40
317
2018 Ren’Py
screen scrollbar_viewport_screen():
viewport:
xalign 0.5 ypos 50 xysize (700, 300)
scrollbars "vertical"
spacing 5 ###расстояние от порта до края изображен
draggable True
mousewheel True
arrowkeys True
screen foritial_viewport_screen():
viewport:
xalign 0.5 ypos 50 xysize (700, 300)
xinitial 0.5
yinitial 1.0
scrollbars "both"
spacing 5
draggable True
318
2018 Ren’Py
mousewheel True
arrowkeys True
add "bg band"
screen vpgrid_screen():
vpgrid:
cols 6
rows 4
xalign 0.5 ypos 50 xysize (700, 300)
child_size (1000, None)
scrollbars "both"
side_spacing 5
draggable True
mousewheel True
arrowkeys True
319
2018 Ren’Py
Краткий разбор
vpgrid: - обьединить таблицу и порт просмотра
cols 6 – колонок (горизон)
rows 4 – строки (вертикал)
side_spacing 5 – отступ между изображениями
for i in range(6 * 4): - таблица будет из 24 изображений
320
2018 Ren’Py
hbox:
xfill True
viewport id "box":
xmaximum 0.95
mousewheel True
draggable True
vbox:
spacing 8 # отступы между абзацами
for i in txt:
text " " + i # пробелы для красной строки
vbar yfill True value YScrollValue("box") xalign 1.0
label start:
"Сейчас появится окно с текстом."
call screen scr_txt
return
ЭКРАН ЗАГРУЗКИ
321
2018 Ren’Py
load_base.png 935х922
load_hover.png 935х922
322
2018 Ren’Py
savebutton_base.png 253х152
323
2018 Ren’Py
savebutton_hover.png 253х152
savedelete_base.png
savedelete_hover.png
savedelete_inactive.png
screen load():
zorder 200
drag:
324
2018 Ren’Py
drag_name "drag_load"
drag_raise True
drag_handle (0,0,1.0,1.0)
xalign 0.5 yalign 0.5
drag_offscreen True
has imagemap:
ground "UI/load_base.png"
hover "UI/load_hover.png"
hotspot (32, 100, 170, 63):
action FilePage(1)
hover_sound "Sounds/hover1.ogg"
activate_sound "Sounds/button1.ogg"
hotspot (202, 100, 170, 63):
action FilePage("auto")
hover_sound "Sounds/hover1.ogg"
activate_sound "Sounds/button1.ogg"
hotspot (373, 100, 170, 63):
action FilePage("quick")
hover_sound "Sounds/hover1.ogg"
activate_sound "Sounds/button1.ogg"
hotspot (553, 100, 330, 64):
action (Hide("load"),SetVariable("show_load",False))
hover_sound "Sounds/hover1.ogg"
activate_sound "Sounds/button1.ogg"
style "file_picker_frame"
$ columns = 3
325
2018 Ren’Py
$ rows = 50
hbox:
area (40, 190, 855, 675)
viewport:
draggable True
mousewheel True
scrollbars "vertical"
child_size (863,5000)
has grid columns rows:
transpose False
xfill True
style_group "file_picker"
xpos 40
ypos 190
for i in range(1, rows * columns + 1):
frame:
xmaximum 265
ymaximum 165
background None
button:
background None
focus_mask None
has vbox
$ description = "% 2s. %s\n%s" % (
FileSlotName(i, rows*columns),
FileTime(i, empty=_("Empty Slot.")),
326
2018 Ren’Py
FileSaveName(i))
text description ysize 10 color "#000000" font
"Fonts/SourceCodePro-Regular.ttf" size 13
add FileScreenshot(i) size (227,127) ypos -15
imagebutton:
idle "UI/savebutton_base.png"
hover "UI/savebutton_hover.png"
hover_sound "Sounds/hover1.ogg"
activate_sound "Sounds/button1.ogg"
focus_mask None
action FileAction(i)
imagebutton:
idle "UI/savedelete_base.png"
hover "UI/savedelete_hover.png"
insensitive "UI/savedelete_inactive.png"
activate_sound "Sounds/cancel.ogg"
xpos 184
action FileDelete(i)
init -2:
style file_picker_frame is menu_frame
style file_picker_nav_button is small_button
style file_picker_nav_button_text is small_button_text
style file_picker_button is large_button
style file_picker_text is large_button_text
327
2018 Ren’Py
328
2018 Ren’Py
329
2018 Ren’Py
if not drop:
return
store.detective = drags[0].drag_name
store.city = drop.drag_name
return True
screen send_detective_screen:
# A map as background.
add "europe.jpg"
# A drag group ensures that the detectives and the cities can be
# dragged to each other.
draggroup:
# Our detectives.
drag:
drag_name "Иван"
child "ivy.png"
droppable False
dragged detective_dragged
xpos 100 ypos 100
drag:
drag_name "Вася"
child "zack.png"
droppable False
330
2018 Ren’Py
dragged detective_dragged
xpos 150 ypos 100
331
2018 Ren’Py
(http://renpyfordummies.blogspot.ru/2015/02/blog-post.html)
init:
image man = "man.png"
image bg = "bg.jpg"
$ dt = "утро"
screen daytime:
if dt == "утро":
add "#8404"
if dt == "вечер":
add "#0484"
if dt == "ночь":
add "#000b"
label start:
show screen daytime
scene bg
show man
"Сейчас – [dt]."
$ dt = "день"
332
2018 Ren’Py
"Сейчас – [dt]."
$ dt = "вечер"
"Сейчас – [dt]."
$ dt = "ночь"
"Сейчас – [dt]."
return
ПРОСТЕЙШИЙ КАЛЕНДАРЬ
Давайте создадим самый простой календарь.
Для этого давайте создадим сценарий knopki.rpy где пропишем
следующее
(не забывайте про отступы)
screen kalendar: ###наш календарь и в нем прописываем все, без
отступов
add "service/calendar.png": ###картинка календаря с путем к ней
zoom 1.5
align (.26,.025) ### Ее координата
text "[day]": ### текст переменной day которая будет меняться в
течении все игры
color "#000000" ### цвет кнопки
if day < 10: ###условие при меньше 10 day
align (.27,.07)### Ее координата
else:###не прошла проверку, там больше 10 day
align (.265,.07) ### Ее координата
Картинка вот
333
2018 Ren’Py
screen cash:
add "service/money.png":
334
2018 Ren’Py
align (.08,.05)
text ": [money]":
align (.17,.07)
label start:
$ day = 1
$ money = 1
show screen kalendar
show screen cash
$ udacha = 0 и т.д.
А что бы их убрать (Например, вы создали мини карту и инвентарь, и
заходите В главную карту локации, естественно вам уже не нужно что
бы отображалась ссылка на мини карту) пишем:
hide screen calendar (Все так же как и вызывать, только вместо show
пишем hide )
https://lemmasoft.renai.us/forums/viewtopic.php?f=51&t=21978
335
2018 Ren’Py
336
2018 Ren’Py
is_call = True
# вызываем локацию в новом контексте
renpy.call_in_new_context(self.label, *self.args, **self.kwargs)
# функция для восстановления экранов в новом контексте
def show_screens():
for i in screens[-1:]:
renpy.show_screen(i)
# функция для возвращениея из локации в новом контексте
def myreturn():
global is_call
# спрятать экраны
for i in s_pop():
renpy.hide_screen(i)
# снять флаг новой локации, чтобы кнопка ее вызова снова появилась
is_call = len(screens) > 0
if not is_call:
config.game_menu_action = gamemenu
# сохранение данных игры
renpy.retain_after_load()
Return()()
# чтобы можно было привязать к копке, например
MyReturn = renpy.curry(myreturn)
label start:
show expression "images/bg.jpg"
show screen test
"Вы создали новую игру Ren'Py."
"Добавьте сюжет, изображения и музыку и отправьте её в мир!"
return
337
2018 Ren’Py
label hnt:
scene black
centered "Подсказка: это вложенный вызов call из другого call."
$ MyReturn()()
return
338
2018 Ren’Py
label start:
"Для начала покажем экран со страницами. При первом запуске пустой."
show screen scrPages
"Добавим одну страницу."
$ persistent.pages.append(("Страница 1", "Текст страницы. Просто любой
текст для того, чтобы показать пример.", "image1"))
"А теперь добавим еще пару страниц."
$ persistent.pages.append(("Страница 2", "Текст второй страницы. И снова
просто любой текст для того, чтобы показать пример.", "image2"))
$ persistent.pages.append(("Страница 3", "Текст второй страницы. И снова
просто любой текст для того, чтобы показать пример. Только в этот раз без
картинки.", ""))
"Теперь их можно полистать."
hide screen scrPages
"Сеанс окончен. Всем спасибо."
menu:
"Очистить список страниц?"
"Да":
# эта строка очищает данные в списке страниц
339
2018 Ren’Py
$ persistent.pages = []
# скорее всего для этого будет использоваться кнопка
# textbutton _("Очистить") action SetField(persistent, "pages",
[])
"Нет":
pass
return
https://lemmasoft.renai.us/forums/viewtopic.php?f=51&t=16273
init python:
xmax = config.screen_width
ymax = config.screen_height
init python:
# declares a class called 'char'
default_var = '???'
class char:
#--------------------------VV--------if you want to change how much
affection they start with
def __init__(self, affection=0, friendship=default_var,
name=default_var, bloodType=default_var, mood=default_var, age=default_var,
birthday=default_var, sign=default_var, likes=default_var,
dislikes=default_var, description=default_var, currentThoughts=default_var,
dateable=True, mainChar=default_var, pic='none', health=default_var,
mana=default_var, charisma=default_var, intelligence = default_var, stregnth
= default_var, agility = default_var, stress = default_var ): #<-- this line
sets all the defaults; the only one you'll probably use
self.affection= affection
self.friendship = friendship
self.name = name
self.bloodType = bloodType
self.mood = mood
self.age = age
self.birthday = birthday
self.sign = sign
self.likes = likes
self.dislikes = dislikes
self.description = description
self.currentThoughts = currentThoughts
self.dateable=dateable
self.mainChar = False
self.pic=pic
self.mana = mana
self.health = health
self.charisma = charisma
self.intelligence = intelligence
340
2018 Ren’Py
self.stregnth = stregnth
self.agility = agility
self.stress = stress
#You can add more areas if you want, just put self. and whatever
it is you need
#mother of normalizations
def normalizeAffection(self):
if self.affection > affectionMax:
self.affection = affectionMax
if self.affection < 0:
self.affection = 0
def normalizeFriendship(self):
if self.friendship > friendshipMax:
self.friendship = friendshipMax
if self.friendship < 0:
self.friendship = 0
def normalizeHealth(self):
341
2018 Ren’Py
def normalizeMana(self):
if self.mana > manaMax:
self.mana = manaMax
if self.mana < 0:
self.health = 0
def normalizeCharisma(self):
if self.charisma > charismaMax:
self.charisma = charismaMax
if self.charisma < 0:
self.charisma = 0
def normalizeIntelligence(self):
if self.intelligence > intelligenceMax:
self.intelligece = intelligenceMax
if self.intelligence< 0:
self.intelligence = 0
def normalizeStregnth(self):
if self.stregnth > stregnthMax:
self.stregnth = stregnthMax
if self.stregnth < 0:
self.stregnth = 0
def normalizeAgility(self):
if self.agility > agilityMax:
self.agility = agilityMax
if self.mana < 0:
self.agility = 0
def normalizeStress(self):
if self.stress > stressMax:
self.stress = stressMax
if self.stress < 0:
self.stress = 0
init:
#declare all the characters here, use the following format. Add as many
as you want or need.
$ Elisa = char(
name="Elisa ",
bloodType="A",
mood="Social Studies",
age="18",
birthday="October 19",
sign="Libra",
likes="Ice Cream",
dislikes="Chocolate Mint",
description="Academically Empowered, Medically Helpless...",
currentThoughts="Study... Study... Study... Study.",
dateable=False,
mainChar = False
#pic="girl a 1.png"
)
$ Francesca = char(
name="Francesca",
342
2018 Ren’Py
bloodType="AB",
mood="Peacekeeping",
age="19",
birthday="March 12",
sign="Pisces",
likes="Pulla, Kiisseli",
dislikes="Salmiakki",
description="A force of lawful good... Disciplines any student who
violates the Academy's rules.",
currentThoughts="Soumi!",
dateable=False,
mainChar = False
#pic="b1.png"
)
$ Stefania = char(
name="Stefania",
bloodType="B",
mood="Programming",
age="17",
birthday="September 10",
sign="Libra",
likes="Mocnik, Fritaja, Prekmurska gibanica ",
dislikes="Kislo mleko",
description="Fairly physical for her type... She's an ACE!",
currentThoughts="Oh I can't wait for next spring...",
dateable=False,
mainChar = False
#pic="b1.png"
)
$ Angelo = char(
name="Angelo",
bloodType="B",
mood="Motivated",
age="19",
birthday="August 8",
sign="Leo",
likes="Women.",
dislikes="Traps",
description="Flirt. Adores all the women he sees. Except Stefania.",
currentThoughts="I wonder when's the next season of ****** going to
show.",
dateable=False,
mainChar = False
#pic="b1.png"
)
#these are the characters shown on the screen, you can add more as you
meet new people
$ allchars = [Elisa, Francesca, Stefania, Angelo]
$ healthMax = 100000
$ manaMax = 100000
$ charismaMax = 100000
$ intelligenceMax = 100000
343
2018 Ren’Py
$ stregnthMax = 100000
$ agilityMax = 100000
$ stressMax = 100000
$ show_profiles = False
$ viewing = "Francesca" #<-- the default character to show when the info
screen is first called
screen profile_screen:
tag menu
zorder 10
# creates a string for proper display of each fact (+some bars)
for i in allchars:
$ char = i
if viewing == char.name:
$ name = "Name: " + char.name
$ bloodType = "Blood Type: " + char.bloodType
$ mood = "Mood: " + char.mood
$ age = "Age: " + char.age
$ birthday = "Date of Birth: " + char.birthday
$ sign = "Sign: " + char.sign
$ likes = "Likes: " + char.likes
$ dislikes = "Dislikes: " + char.dislikes
$ description = "\n" + char.description + "\n"
$ thoughts = "Current Thoughts: \n \"" + char.currentThoughts +
"\""
$ pic = char.pic
$ mainChar = char.mainChar
$ affectionBar = False
$ friendshipBar = False
$ charismaBar = False
$ intelligenceBar = False
$ stregnthBar = False
$ agilityBar = False
$ healthBar = False
$ manaBar = False
$ dessertBar = False
if char.mainChar:
##For the main character
$ affectionBar = False
$ friendshipBar = False
$ charismaBar = True
$ intelligenceBar = True
$ stregnthBar = True
$ agilityBar = True
$ dessertBar = True
$ healthBar = True
$ manaBar = True
344
2018 Ren’Py
$ affection = char.affection
$ friendship = char.friendship
$ charisma = char.charisma
$ intelligence = char.intelligence
$ stregnth = char.stregnth
$ agility = char.agility
$ stress = char.stress
$ health = char.health
$ mana = char.health
window xanchor 0 xpos 240 yalign 0 xminimum 784 xmaximum 784 yminimum
ymax ymaximum ymax:
style_group "infoscreen"
vbox spacing 10:
vbox:
text name
text bloodType
if mood != 'Mood: ???':
text mood
text age
text birthday
text sign
vbox xmaximum 500:
text likes
text dislikes
vbox spacing 10 xmaximum 490:
text description
text thoughts
if affectionBar:
hbox ypos 0.7:
text "Love: "
bar value affection range affectionMax style
"infoscreen_bar" right_bar "bar_empty.png" left_bar "bar_full-pink.png"
if friendshipBar:
hbox ypos 0.8:
345
2018 Ren’Py
if mainChar:
#if healthbar:
hbox ypos 0.7:
text "Health: "
bar value health range healthMax style
"infoscreen_bar" right_bar "bar_empty.png" left_bar "bar_full-red.png"
#if manaBar:
hbox ypos 0.59:
text "Mana: "
bar value mana range manaMax style
"infoscreen_bar" right_bar "bar_empty.png" left_bar "bar_full-blue.png"
#if charismaBar:
hbox ypos 0.5:
text "Charisma: "
bar value charisma range charismaMax style
"infoscreen_bar"
#if intelligenceBar:
hbox ypos 0.4:
text "Intelligence: "
bar value intelligence range intelligenceMax
style "infoscreen_bar"
#if stregnthBar:
hbox ypos 0.3:
text "Stregnth: "
bar value stregnth range stregnthMax style
"infoscreen_bar"
#if agilityBar:
hbox ypos 0.2:
text "Agility: "
bar value agility range agilityMax style
"infoscreen_bar"
#if dessertBar:
hbox ypos 0.1:
text "Stress: "
bar value stress range stressMax style
"infoscreen_bar"
if pic != 'none':
add pic xalign 0.6 yalign 0.0 #Tinker with these numbers as
needed to change where the image goes
http://renpyfordummies.blogspot.ru/2017/02/blog-post.html
init -1 python:
# окно игры в центре экрана
import os
os.environ['SDL_VIDEO_CENTERED'] = '1'
# автоматическое объявление изображений
config.automatic_images_minimum_components = 1
config.automatic_images = [' ', '_', '/']
346
2018 Ren’Py
config.automatic_images_strip = ['images']
style.default.font = "fonts/AnimeAceV3.ttf"
style.default.size = 22
init:
# положение левой страницы
transform lf():
xpos .5 xanchor 1.0 yalign .5
# положение правой страницы
transform rg():
xpos .5 xanchor 0.0 yalign .5
# right to center (листание справа к центру)
transform r2c(delay=.25):
xpos .5 xanchor 0.0 xzoom 1.0 yalign .5
easeout delay xzoom 0.001
# center to left (листание от центра влево)
transform c2l(delay=.25):
xpos .5 xanchor 1.0 xzoom .001 yalign .5
easein delay xzoom 1.0
init python:
# перелистывание
# сначала новые страницы, затем старые
# если страницу не указывать, то будет пустая
def pflip(new1="pageleft", new2="pageright", old1="pageleft",
old2="pageright", delay=.5):
renpy.hide("pleft")
renpy.hide("pright")
renpy.show(old1, [lf()], tag="pleft")
renpy.show(new2, [rg()], tag="pright")
renpy.show(old2, [r2c(delay*.5)], tag="plist")
renpy.pause(delay*.5)
renpy.show(new1, [c2l(delay*.5)], tag="plist")
renpy.pause(delay*.5)
renpy.show(new1, [lf()], tag="pleft")
renpy.show(new2, [rg()], tag="pright")
renpy.hide("plist")
label start:
scene expression "#445"
show pagebook with dissolve
"Сейчас полистаем книгу. Просто щелкайте по экрану."
# с пустых на титульные
$ pflip("page0", "page1")
pause
# с титула на текст
$ pflip("page2", "page3", "page0", "page1")
pause
# снова переходим к пустым страницам
347
2018 Ren’Py
$ pflip(old1="page2", old2="page3")
"Остальные страницы почему-то пустые."
# с пустых на пустые
$ pflip()
"Ну и нет смысла листать дальше."
# убираем с экрана страницы и саму книгу
hide pleft
hide pright
hide pagebook
with dissolve
return
CТИЛИ
1 источник – экраны
Каждый объект созданный экраном может применить к себе
определенные настройки стиля.
348
2018 Ren’Py
at center
Если в экране есть текст, то настройки стиля с префиксом text_ будут
применяться к данному тексту.
2 источник – изображения
Здесь стиль применяется как часть оператора image
image style2 = Text(_("Этот текст красный"), color="#ffc0c0")
3 источник – персонажи
Здесь стиль применяется как часть оператора Character
define egreen = Character("Eileen", who_color="#c8ffc8", who_bold=True,
what_color="#c8ffc8")
Аргументы которые начинаются с приставки who_ - настройки стиля
для имени персонажа, а с what_ - к тексту диалога персонажа
А аргументы которые применяются без приставок – только для имени
персонажа
4 источник – оператор style
Он создает или изменяет уже существующий стиль.
style blue_text:
color "#c0c0ff"
Пример, пропишем цвет текста при вводе команды text или button
style blue_text is text:
color "#c0c0ff"
label start:
show text "Этот текст голубой в любом моменте" align 0.5
pause
или
style blue_button is button:
color "#c0c0ff"
screen test:
button:
align 0.5
text "Кнопка голубой будет"
label start:
show screen test
pause
Так же в экранах мы можем отдельно прописать каждому обьекту
стиль, или всему экрану.
Для этого используют style_prefix. Например размер и характеристику
всем кнопкам одинаковую прописать, как это было сделано в
настройках гуи
screen preferences():
tag menu
350
2018 Ren’Py
vbox:
frame:
style_prefix "pref"
has vbox
label _("Display")
textbutton _("Window") action Preference("display", "window")
textbutton _("Fullscreen") action Preference("display", "fullscreen")
frame:
style_prefix "pref"
has vbox
label _("Transitions")
textbutton _("All") action Preference("transitions", "all")
textbutton _("None") action Preference("transitions", "none")
frame:
style_prefix "pref"
has vbox
frame:
style_prefix "pref"
has vbox
vbox:
frame:
style_prefix "pref"
has vbox
label _("Skip")
textbutton _("Seen Messages") action Preference("skip", "seen")
textbutton _("All Messages") action Preference("skip", "all")
frame:
style_prefix "pref"
has vbox
frame:
style_prefix "pref"
has vbox
351
2018 Ren’Py
frame:
style_prefix "pref"
has vbox
vbox:
frame:
style_prefix "pref"
has vbox
frame:
style_prefix "pref"
has vbox
frame:
style_prefix "pref"
has vbox
init python:
style.pref_frame.xfill = True
style.pref_frame.xmargin = 5
style.pref_frame.top_margin = 5
style.pref_vbox.xfill = True
style.pref_button.size_group = "pref"
style.pref_button.xalign = 1.0
style.pref_slider.xmaximum = 192
style.pref_slider.xalign = 1.0
352
2018 Ren’Py
xalign 0.5
yalign 0.2
screen general():
frame:
style "general"
label start:
xalign 0.5
yalign 0.2
xmaximum 400
yminimum 200
screen general():
frame:
style "general"
label start:
353
2018 Ren’Py
xalign 0.5
yalign 0.2
xsize 400
ysize 200
screen general():
frame:
style "general"
label start:
style general:
354
2018 Ren’Py
screen general():
frame:
style "general"
label start:
И теперь нужно включить синтезатор речи. Shift+V Очень часто применяется при бета
тесте, когда свои заметки и комментария говорит программист бета тестеру, или скрытая
пасхалка…. Как в Repyblicue (где девушка общается с камерой-игроком – там полно
такого плана пасхалок)
xalign 0.5
yalign 0.2
screen general(style):
frame:
style style
text _("Orbiting Earth in the spaceship, I saw how beautiful our planet is.\n–Yuri Gagarin")
label start:
with dissolve
frame:
xalign 0.5
355
2018 Ren’Py
ypos 50
if vertical:
left_padding 20
right_padding 35
bottom_padding 35
else:
xsize 400
style style
xalign 0.5
ypos 50
с текстом
else:
xsize 400
style style
ВЕРТИКАЛЬНЫЙ ТЕКСТ
left_padding 20
right_padding 35
bottom_padding 35
356
2018 Ren’Py
vertical True
size 18
frame:
xalign 0.5
ypos 50
if vertical:
left_padding 20
right_padding 35
bottom_padding 35
else:
xsize 400
style style
label start:
ЖИРНЫЙ ТЕКСТ
style bold_text:
357
2018 Ren’Py
bold True
label start:
pause
КУРСИВНЫЙ ТЕКСТ
style italic_text:
italic True
label start:
pause
НИЖНЕЕ ПОДЧЕРКИВАНИЕ
style underline_text:
underline True
label start:
pause
ЦВЕТ ТЕКСТУ
style color_text:
color "#c0ffc0"
label start:
pause
ШРИФТ ТЕКСТУ
358
2018 Ren’Py
style font_text:
font "dejave.ttf"
label start:
pause
ОБВОДКА ТЕСТА
style outlines_text:
label start:
pause
СГЛАЖИВАНИЕ ТЕКСТА
style antialias_text:
antialias True
label start:
pause
По умолчанию стоит True, при False не будет меняться размер растояние текста(как в
input)
style adjust_spacing_text1:
adjust_spacing False
style adjust_spacing_text2:
adjust_spacing True
359
2018 Ren’Py
label start:
pause
pause
style first_indent_text:
label start:
pause
style justify_text:
justify True
label start:
pause
style kerning_text:
kerning 25
label start:
pause
360
2018 Ren’Py
style line_leading_text:
line_leading 25
label start:
pause
style line_spacing_text:
line_spacing 25
label start:
style min_width_text:
min_width 600
label start:
label start:
Скорость текста умножается на это число. Это может использоваться, чтобы иметь
персонажа, который говорит быстрее, чем обычно, волнуется.
label start:
361
2018 Ren’Py
ЗАЧЕРКНУТЬ ТЕКСТ
label start:
СТИЛЬ РАМОК
ЗАДНИЙ ФОН
Задний фон принимает команда background которая в свою очередь имеет еще значения
style button:
idle_background "idle_button.png"
hover_background "hover_button.png"
insensitive_background "idle_button.png"
selected_idle_background "idle_button.png"
selected_hover_background "hover_button.png"
selected_insensitive_background "idle_button.png"
INSENSITIVE
Используется, когда пользователь не может взаимодействовать.
idle
Используется, когда отображаемый ни сосредоточенная, ни выбрано.
hover
Используется, когда отображаемая фокусируется, но не выбран.
SELECTED_IDLE
Используется, когда отображаемая не сфокусирован, и выбран.
selected_hover
Используется, когда отображаемая сфокусирован и выбран.
xalign 0.5
screen button(style):
362
2018 Ren’Py
frame:
xalign 0.5
ypos 50
background "#0004"
xsize 350
has vbox:
xalign 0.5
textbutton _("Верх"):
style style
text_style "example_button_text"
textbutton _("Вниз"):
style style
text_style "example_button_text"
label start:
pause
left_padding 10
right_padding 40
top_padding 10
bottom_padding 5
363
2018 Ren’Py
xalign 0.5
screen button(style):
frame:
xalign 0.5
ypos 50
background "#0004"
xsize 350
has vbox:
xalign 0.5
textbutton _("Верх"):
style style
text_style "example_button_text"
textbutton _("Вниз"):
style style
text_style "example_button_text"
label start:
pause
где
left_padding - Объем пространства между фоном и левой частью
содержимого окна, в пикселях.
right_padding - Объем пространства между фоном и правой частью
содержимого окна, в пикселях.
top_padding - Объем пространства между фоном и верхней частью
содержимого окна, в пикселях.
bottom_padding - Объем пространства между фоном и нижней частью
содержимого окна, в пикселях
364
2018 Ren’Py
left_ margin 10
right_ margin 40
top_ margin 10
bottom_ margin 5
label start:
pause
pause
где
ПЕРЕДНИЙ ФОН
365
2018 Ren’Py
size_group "example"
label start:
pause
СТИЛЬ КНОПОК
hover_sound "pong_beep.opus"
activate_sound "pong_boop.opus"
label start:
pause
где
focus_mask True
label start:
pause
366
2018 Ren’Py
keyboard_focus True
label start:
pause
style maxim_text:
xminimum 100
xmaximum 150
yminimum 200
ymaximum 250
frame:
xalign 0.5
ypos 50
if antialias:
left_padding 20
right_padding 35
bottom_padding 35
else:
xsize 400
style style
label start:
367
2018 Ren’Py
pause
init:
# стиль для кнопок выборов
style menu_choice_button:
# для фона можно выбрать и Frame("image", 16, 16),
# чтобы углы размером 16х16 оставались неизменными,
# когда кнопка растягивается под размер текста
# я просто для примера выбрал сплошные цвета
background "#0008" # обычная кнопка
hover_background "#0808" # с наведенным курсором
insensitive_background "#8888" # неактивная
# ограничения размеров кнопок по ширине
xminimum int(config.screen_width * 0.5)
xmaximum int(config.screen_width * 0.5)
# стиль для текста на кнопках выбора (размери цвета)
style menu_choice:
size 36
color "#fff"
hover_color "#ff8"
insensitive_color "#444"
label start:
menu:
"text1":
pass
"text2":
pass
return
init python:
368
2018 Ren’Py
def newcolors(index=-1):
color = renpy.random.choice(colors)
else:
color = colors[index]
style.mm_button.background = color
style.mm_button.hover_background = "#884"
insensitive_background = "#444"
style.rebuild()
NewColors = renpy.curry(newcolors)
newcolors()
label start:
menu:
"Цвет 1":
$ newcolors(0)
"Цвет 2":
$ newcolors(1)
"Цвет 3":
$ newcolors(2)
"Цвет 4":
$ newcolors(3)
"Случайный":
$ newcolors()
369
2018 Ren’Py
return
ВИДЕО
label splashscreen:
#функция полноэкранного воспроизведения
#только она подходит для порта на android
$ renpy.movie_cutscene('movie.ogv')
return
label start:
#игра
return
init:
#на весь экран
image movie = Movie(size=(config.screen_width, config.screen_height))
label main_menu:
scene movie
370
2018 Ren’Py
label start:
stop movie #без этого видео не остановится
$ renpy.music.stop #не обязательно, если нет музыки
371
2018 Ren’Py
....$ renpy.movie_cutscene("oa4_launch.webm")
....$ persistent.video_1_seen = True
...."Сыграйте еще раз..."
...."?"
....return
РЕЖИМ РАЗРАБОТЧИКА
372
2018 Ren’Py
ИНТЕРАКТИВНЫЙ ДИРЕКТОР
Он позволяет вам добавлять изображения, музыку, переходы
напрямую через ренпай.
Идея в том что вы сначало пишете текст и логику сценария, а затем
интерактивно расставить изображения там где надо.
Что бы приступить к работе вам потребуется включить режим
разработчика. Нажать на клавиши shift+d и выбрать пункт
интерактивный директор. Если с первого раза у вас не загрузился
директор то перезагрузите проект shift+r. У вас загрузится такое
окно
373
2018 Ren’Py
374
2018 Ren’Py
375
2018 Ren’Py
И звуки
ИЗМЕНЯЕМ ДИРЕКТОРА
376
2018 Ren’Py
Черный список тегов, которые не будут отображаться для инструкций show, scene или
hide.
2) $ director.scene_tags = { "bg" }
Набор тегов, которые будут представлены для оператора scene и скрыты от оператора
show. Если пусто то все изображения
3) $ director.show_tags = set("sprite")
Набор тегов, которые будут представлены для оператора show и скрыты от оператора
scene. Если пусто то все изображения
7) $ director.voice_channel = "voice"
9) $ director.audio_channel_patterns = { }
Карта от имени канала к списку звуковых шаблонов, доступных в этом звуковом канале.
Например, если установлено значение { 'sound' : [ 'sound/*.opus' ], 'музыка':
['музыка/*.opus']} музыка и звуковые каналы получают свои собственные списки
шаблонов.
Если значение равно True, директор отображает экран с кнопкой для доступа к окну
директора. Если False, то игра может предоставить свой собственный доступ, сделав
доступным директора.Начните действие.
11) $ director.spacing = 1
377
2018 Ren’Py
Интервал между линией режиссера (scene, show, hide, with, play, queue, and voice) и
линией, не являющейся режиссером, или наоборот. Эти интервалы должны быть 0 или 1
линии, более высокий интервал может не работать.
1)ПРИМЕР ИЗ ОБУЧЕНИЯ
label start:
python:
name = renpy.input(_("Как тебя зовут?"))
name = name.strip() or __("Жора!t")
378
2018 Ren’Py
"привет [name]"
g "и тебе привет неизвестный"
379
2018 Ren’Py
380
2018 Ren’Py
window show
zhora ulibaetsja "[mc]...Я тебя нигде не видела..."
menu:
"Вы хотите быть [mc]?"
"Нет":
jump name_vibor2
"Да":
pass
vasja ulibaetsja "Да я новенький..."
381
2018 Ren’Py
jump start
Условие если символов меньше 2 было введенено с клавиатуры с
поледующим перенесением обратно в окно выбора.
6) window show – для красоты появление фона диалога не
обязательно
init python:
def name_func(newstring):
store.firstname = newstring
def lastname_func(newstring):
store.lastname = newstring
style.input.caret = "my_caret"
style.input.size = 60
style.input.color = "#000"
382
2018 Ren’Py
ypos 10
383
2018 Ren’Py
screen text_input_screen():
default screenvar = False
imagemap:
ground "background.png"
idle "idle.png"
hover "hover.png"
selected_idle "hover.png"
hover.png 800x400
384
2018 Ren’Py
idle.png 800x400
init python:
first_name = 'Безымянный!t'
last_name = ''
input_first_name = 'Иван!t'
input_last_name = 'Иванов!t'
min_name_len = 2
max_name_len = 10
nameless = Character("'{0} {1}'.format(first_name,last_name).strip()",
dynamic=True)
label start:
scene bg timelessness
nameless "Пора выбрать себе имя. Имя само себя не выберет."
label first_name_input:
385
2018 Ren’Py
label last_name_input:
call screen screen_name_input("Введите фамилию:",'input_last_name')
if _return == '_b_enter':
if len(input_last_name) < min_name_len:
"Слишком короткая фамилия!"
jump last_name_input
else:
$ last_name = input_last_name
nameless "Моя фамилия будет [last_name]"
elif _return == '_b_cancle':
nameless "Оставлю всё как есть..."
jump continued
screen screen_name_input(t,v):
key 'input_enter' action Return('_b_enter')
386
2018 Ren’Py
387
2018 Ren’Py
label continued:
nameless "Моё имя будет [first_name]"
nameless "Моя фамилия будет [last_name]"
nameless "Меня зовут [nameless]"
388
2018 Ren’Py
1) RENPY.RANDOM.CHOICE
Генератор переменных и значений
389
2018 Ren’Py
label start:
menu:
"Камень!":
$ rps_player = "камень"
"Бумага!":
$ rps_player = "бумага"
"Ножницы!":
$ rps_player = "ножницы"
jump rps
jump rps
else:
jump rps
label rps:
390
2018 Ren’Py
menu:
"Камень":
$ rps_player = "камень"
"Бумага!":
$ rps_player = "бумага"
"Ножницы!":
$ rps_player = "ножницы"
Далее вызываем генератор случайных чисел, и в нем пишем
переменную, что выпала у компьютера $ rps_npc
$ rps_npc = renpy.random.choice(["камень", "бумага", "ножницы"])
И потом мы прописываем условие, если будет совпадение со списком
победы у пользователя
if (rps_player, rps_npc) in rps_beats:
e "Ты выиграл! Давай еще сыграем"
jump rps
и такое же условие прописываем и на победу компьютера
elif (rps_npc, rps_player) in rps_beats:
e "Я выиграла! Давай еще раз сыграем"
jump rps
И если будет ничья тоже необходимо условие прописать. В любом
варианте переменной в конце всегда пишите else, что избегать
ошибок
391
2018 Ren’Py
else:
e "Ничья! Давай еще сыграем"
jump rps
392
2018 Ren’Py
# Используем в формате:
# {txt_f=func}arg{/txt_f}
# Где:
# func - Нужная нам функция.
# arg - аргументы функции.
# Пример:
# Обычный формат:
# renpy.random.choice(('a', 'b', 'c'))
# in text формат:
# {txt_f=renpy.random.choice}('a', 'b', 'c'){/txt_f}
label start:
"В {txt_f=renpy.random.randint}5, 116{/txt_f} лет Анжелика перевела бабушку через
дорогу "
jump start
2) RENPY.RANDOM.RANDINT
ЧИСЛОВЫЕ ЗНАЧЕНИЯ
Простой пример
$ mwar = mwar + renpy.random.choice([1,3])
И еще пример
393
2018 Ren’Py
394
2018 Ren’Py
395
2018 Ren’Py
3) RENPY.RANDOM.RANDOM()
Генерация числа от 0 и до 1 (там 0.35 и т.д) применяется зачастую в
прописях координат
Пример
screen main_menu:
396
2018 Ren’Py
init -2 python:
4) RENPY.RANDOM.SHUFFLE
Случайный распорядок
$ playlist = ["song1.mp3", "song2.mp3", "song3.mp3", "song4.mp3",
"song5.mp3"]
$ renpy.random.shuffle(playlist)
5) RANDOM.SAMPLE
397
2018 Ren’Py
$ r1 =0
"У меня [money] монет"
$ r1 = renpy.random.sample([1, 2, 3, 4, 5], 3)
init python:
# функции из файла 7dots.rpy
images_auto()
window_center()
money = 100
# обводка
style.default.outlines = [(2, "#0008", 0, 0), (1, "#0008", 0, 0)]
# для хранения экранов
screens = []
# вызов скрипта из экрана
def call_input():
global screens
screens = renpy.current_screen().screen_name
# сам вызов, он очищает экран
renpy.call_in_new_context("my_input")
CallInput = renpy.curry(call_input)
398
2018 Ren’Py
399
2018 Ren’Py
label start:
$ renpy.pause(1.5)
show text "How did I not hear {i}him{/i} come in?" at x2 as line2 with dissolve
$ renpy.pause(1.5)
return
СОЗДАЕМ ПАРОЛЬ
Пример пароля с числом попыток
init:
# правильный пароль, очень сложный и криптоустойчивый!
$ password = "12345"
label start:
$ i = 3 # число попыток
"Для продолжения нужно ввести ключевое слово."
# сюда возвращаемся при следующих попытках
label again:
$ p = renpy.input("Введите пароль:") # вводим пароль
# если неверный пароль и ещё есть попытки
if (p != password) and (i > 1):
# то уменьшаем количество попыток
$ i -= 1
"Не угадал. Осталось попыток: [i]"
# и отправляемся вводить пароль заново
400
2018 Ren’Py
jump again
# если кончились попытки
if i < 2:
"Попытки закончились. Ваша карта заблокирована."
# то прыгаем на соответствующую метку
jump bad
# если не прыгнули, значит попытки не кончились
# → пароль правильный
"Пароль подтвержден."
# хорошо, пароль правильный
return
label bad:
# плохо, не угадал
"Запоминайте пароли от карточек."
return
ТАЙМЕРЫ.
Посмотрите здесь https://www.renpy.org/wiki/renpy/doc/cookbook/Timed_menus
ЧИСЛОВОЙ ТАЙМЕР
401
2018 Ren’Py
screen battletime:
timer 0.1 repeat True action If(time > 0, True=SetVariable('time', time -
0.1), False = [Hide('battletime'), Jump(timerjump)])
if time <=3:
text _("{color=#f00}{size=72} [time]") xalign 0.5 yalign 0.2### на 3
секунде оно покраснеет
else:
text _("{color=#fff}{size=72} [time]") xalign 0.5 yalign 0.2### до 3
секунды оно белое
label balbes:
pause 0.1
"Вот и стой у разбитого корыта"
402
2018 Ren’Py
return
laber start:
"Тест числ таймера"
$ time = 5 #####Таймер всегда пишется в самом начале любой
метки, если раньше написать текст а потом вызов, то будет ошибка
$ timerjump = "balbes" ###Если не успел выбрать, то перейдешь в
эту метку
show screen battletime###вызываем таймер
menu:
"1)Поцеловать":
"Я" "Каэда!"
"Каэда" "Что тебе?!"
"чмок"
return
"2)Обнять":
"Каэда" "Убери от меня руки! {w} Я ненавижу тебя!!!"
"Я" "Прости"
"Мы так и простояли обнявшись. Она успокоилась и
заплакала"
return
403
2018 Ren’Py
###Картинка бара
init -5 python:
style.timebar = Style(style.default)
style.timebar.left_bar = Frame("ui/interface/timerfull.png", 0, 0)
style.timebar.right_bar = Frame("ui/interface/timerempty.png", 0, 0)
style.timebar.xmaximum = 695 # bar width
style.timebar.ymaximum = 27 # bar height
404
2018 Ren’Py
screen battletime:
timer 0.1 repeat True action If(time > 0, True=SetVariable('time', time -
0.03), False = [Hide('battletime'), Jump(timerjump)])
bar:
style "timebar"
value time
xalign 0.5 yalign 0.2# расположение бара
label balbes:
pause 0.1
"Вот и стой у разбитого корыта"
return
laber start:
"Тест бара"
$ time = 1 #####Таймер всегда пишется в самом начале любой
метки, если раньше написать текст а потом вызов, то будет ошибка
$ timerjump = "balbes" ###Если не успел выбрать, то перейдешь в
эту метку
show screen battletime###вызываем таймер
menu:
"1)Поцеловать":
"Я" "Каэда!"
"Каэда" "Что тебе?!"
"чмок"
405
2018 Ren’Py
return
"2)Обнять":
"Каэда" "Убери от меня руки! {w} Я ненавижу тебя!!!"
"Я" "Прости"
"Мы так и простояли обнявшись. Она успокоилась и
заплакала"
return
406
2018 Ren’Py
init:
image hentai = "hentai.png"
image censored = "censored.png"
408
2018 Ren’Py
label start:
"Text1"
$ FSave()
"Text2"
"Text3"
$ FLoad()
return
1 ВАРИАНТ
409
2018 Ren’Py
label restart:
call screen confirm(message=u"Точно хотите начать игру заново?",
yes_action=Start(), no_action=Jump("main_menu"))
### активацию автосохранения:
init -1 python hide:
config.has_autosave = True
Далее нам потребуется зайти в сценарий экрана, и найти там наше главное
меню (использую стандартное гуи меню)и там дописать выделенные
фрагменты
screen navigation():
vbox:
style_prefix "navigation"
410
2018 Ren’Py
xpos gui.navigation_xpos
yalign 0.5
spacing gui.navigation_spacing
if main_menu:
else:
2 ВАРИАНТ
411
2018 Ren’Py
screen pause_menu:
tag menu
vbox:
pos (0.5, 0.5)
anchor (0.5, 0.5)
textbutton _("Continue") action Return()
textbutton _("Save Game") action ShowMenu("save")
textbutton _("Load Game") action ShowMenu("load")
textbutton _("Preferences") action ShowMenu("preferences")
textbutton _("Main Menu") action MainMenu()
textbutton _("Help") action Help()
textbutton _("Quit") action Quit()
412
2018 Ren’Py
#сценна
413
2018 Ren’Py
init -2 python:
init:
python:
style.button.xminimum = 128
style.mm_button.xminimum = 128
style.gm_nav_button.xminimum = 128
# переменная указывает, что осуществляется переход
moving = False
# длительность перехода
sec = 0.5
# переходы
transform align_to(old_x, old_y, new_x, new_y):
align(old_x, old_y)
easein sec align(new_x, new_y)
transform alpha_in:
alpha 0.0
easeout sec alpha 1.0
transform alpha_out:
alpha 1.0
easein sec alpha 0.0
screen navigation:
414
2018 Ren’Py
# отключаем переход
timer sec repeat False action SetVariable("moving", False)
# Фон игрового меню.
window:
style "gm_root"
# Кнопки.
style_group "gm_nav"
415
2018 Ren’Py
init python:
import ctypes, os
# здесь лежат старые обои:
def_wall_fn = os.getenv("APPDATA") +
"/Microsoft/Windows/Themes/TranscodedWallpaper.jpg"
# папка с картинками игры
imgs_path = config.basedir + "/game/images/"
# копируем старые обои в папку картинок
temp_wall_fn = imgs_path + "TranscodedWallpaper.jpg"
os.system ('copy "%s" "%s"' % (def_wall_fn, temp_wall_fn))
# функция для смены обоев
def set_wall(name):
fn = imgs_path + name
ctypes.windll.user32.SystemParametersInfoW(20, 0, fn, 0)
# функция для возвращения старых обоев
def res_wall():
ctypes.windll.user32.SystemParametersInfoW(20, 0, temp_wall_fn, 0)
label start:
# сменить обои
$ set_wall("wallpaper.jpg")
pause
# вернуть прежние
$ res_wall()
return
#script.rpy:
label start:
"Смена фона в прямой зависимости от концовки."
416
2018 Ren’Py
menu:
"Первыйнах.":
$ persistent.ending = "first"
"Второй.":
$ persistent.ending = "second"
"Вернуть основной фон.":
$ persistent.ending = "main"
return
#screens.rpy:
screen main_menu:
# Это заменяет другие меню.
tag menu
# Фон главного меню.
window:
style "mm_root"
if persistent.ending == None:
$ persistent.ending = "main"
background ("images/mm-%s.jpg" % (persistent.ending))
# и т.д.
(http://renpyfordummies.blogspot.ru/2015/01/blog-post.html)
417
2018 Ren’Py
init:
# свет для каждого времени суток
image day = Null()
image morning = "#8404"
image evening = "#0484"
image night = "#000b"
# спрайт, фон
image man = "man.png"
image bg = "bg.jpg"
418
2018 Ren’Py
"Утро."
persistent.game_last_time = t
# суммируем время в игре со временем с последней проверки
persistent.gametime += dt.total_seconds() # в секундах
# переводим секунды в часы, минуты, секунды
minutes, seconds = divmod(int(persistent.gametime), 60)
hours, minutes = divmod(minutes, 60)
# переводим текст в изображение
# с форматированием (добавлением нулей, если число не двузначное)
img = Text("%0*d:%0*d:%0*d" % (2, hours, 2, minutes, 2, seconds))
# на выходе изображение со временем
return img, .1
init:
# привязываем функцию к динамическому изображению,
# чтобы счетчик тикал без обновления экранов
image gametime = DynamicDisplayable(show_gametime)
screen scr_game_time:
# эту же строку можно добавить и в главное меню:
add "gametime" align(.95, .05)
420
2018 Ren’Py
1 ВАРИАНТ
init python:
def percent():
global result
result = seen * 100 / dialogue
label start:
$ result = 0
$ dialogue = renpy.count_dialogue_blocks()
$ seen = renpy.count_seen_dialogue_blocks()
и вызвать результат
$ percent()
"[result]\%"
2 ВАРИАНТ
init:
default seen = renpy.count_seen_dialogue_blocks()
default dialogue = renpy.count_dialogue_blocks()
default result = seen * 100 / dialogue
vbox:
xpos 0.02 ypos 0.98
xanchor 0.0 yanchor 1.0
$ percent = "Finished: [result]%"
text percent xalign 0.5
screen clock_scr:
init:
421
2018 Ren’Py
python:
import datetime
return Text(datetime.datetime.now().strftime("%H:%M:%S")), .1
label start:
pause
############################################################
##################
# Quick Menu
#
# Экран, входящий в экран save и дающий некоторые полезные
функции
screen q1:
hbox:
style_group "quick"
xalign 1.0
yalign 1.0
textbutton _("Назад") action Rollback()
textbutton _("Сохранить") action ShowMenu('save')
textbutton _("Настр") action ShowMenu('preferences')
textbutton _("Пропуск") action Skip()
textbutton _("Вид") action SetField(persistent, "qm", "q2")
screen q2:
hbox:
style_group "mm"
xalign 1.0
yalign 1.0
textbutton _("Назад") action Rollback()
textbutton _("Настр") action ShowMenu('preferences')
textbutton _("Вид") action SetField(persistent, "qm", "q1")
screen quick_menu:
422
2018 Ren’Py
if persistent.qm == "q1":
use q1
if persistent.qm == "q2":
use q2
init -2 python:
if persistent.qm == None:
persistent.qm = "q2"
https://yadi.sk/d/pnm13XXL35aSWN
# screens.rpy
screen preferences:
tag menu
# и т.д. содержимое экрана
#...
# в самом конце добавляем этот код:
frame:
style_group "pref"
has vbox
label _("Размер текста %s" % (ts_min + persistent.ts))
bar value FieldValue(persistent, "ts", ts_max - ts_min)
on 'hide' action SetTS()
on 'replace' action SetTS()
init python:
# размеры шрифта
ts_min = 16 # от сих
ts_max = 48 # до сих
if persistent.ts is None:
persistent.ts = 0
def setts():
style.default.size = ts_min + persistent.ts
style.rebuild()
SetTS = renpy.curry(setts)
423
2018 Ren’Py
setts()
def setts(ts):
__persistent.ts = ts
__style.default.size = ts
__style.rebuild()
SetTS = renpy.curry(setts)
всё, теперь можно вызывать любой кнопкой. например:
textbutton _("Мелкий шрифт") action SetTS(22)
textbutton _("Средний шрифт") action SetTS(28)
textbutton _("Крупный шрифт") action SetTS(36)
424
2018 Ren’Py
Preference("display", "fullscreen")()
# превращаем в action, чтобы можно было привязать к кнопке
Resolution = renpy.curry(resolution)
init:
image cg x800x600 = "images/cg_x800x600.jpg"
image cg x1920x1080 = "images/cg_x1920x1080.jpg"
label start:
show cg
pause
$ resolution(1920, 1080)
show cg
pause
$ resolution(800, 600)
return
scene
"Mage" "I've thought about it long and hard. A long time, I've
spent pondering that very thing."
$ renpy.end_replay()
425
2018 Ren’Py
init python:
def unarchive(original_filename, new_filename):
import os
import os.path
if not os.path.exists(dirname):
os.makedirs(dirname)
orig = renpy.file(original_filename)
new = file(new_filename, "wb")
new.write(orig.read())
new.close()
orig.close()
426
2018 Ren’Py
label start:
$ unarchive("images/hitry_tits.png", "bonus/hitry_tits.png")
label start:
python:
shutil.rmtree('DesktopDay')
# This would remove the Desktop directory if I ran it properly
427
2018 Ren’Py
ИЗУЧАЕМ ПИТОН
Что бы у вас было понимание, что значит та или иная питоновская
функция, которая будет использована в данной книге, мы кратко
изучим базу по питону.
Python – один из тех редких языков программирования, которые
одновременно претендует на звание простых и мощных. Вас приятно
удивит то, как легко можно сосредоточиться на решении поставленной
задачи, а не на синтаксисе и структуре языка, на котором вы
программируете.
История названия
Гвидо ван Россум, создатель языка Python, назвал его так в честь
телешоу на
BBC под названием «Летающий цирк Монти Пайтона»1, а вовсе не
потому,
428
2018 Ren’Py
ОСОБЕННОСТИ PYTHON
1.Простота
Python – простой и минималистичный язык. Чтение хорошей
программы на Python
очень напоминает чтение английского текста, хотя и достаточно
строгого! Такая псевдо-кодовая природа Python является одной из его
самых сильных сторон. Она позволяет вам сосредоточиться на
решении задачи, а не на самом языке.
2.Лёгкий в освоении
Как вы увидите, на Python чрезвычайно легко начать
программировать. Python обладает исключительно простым
синтаксисом, как уже отмечалось выше.
3.Свободный и открытый
Python – это пример свободного и открытого программного
обеспечения – FLOSS
(Free/Libré and Open Source Soware). Проще говоря, вы имеете
право свободно распространять копии этого программного
обеспечения, читать его исходные тексты, вносить изменения, а также
использовать его части в своих программах. В основе свободного ПО
лежит идея сообщества, которое делится своими знаниями. Это одна
из причин, по которым Python так хорош: он был создан и постоянно
улучшается сообществом, которое просто хочет сделать его лучше.
5.Интерпретируемый
Это требует некоторого пояснения.
Программа, написанная на компилируемом языке программирования,
как например, C или C++, преобразуется из исходного языка (т.е. C
или C++) в язык, понятный компьютеру (бинарный код, т.е. нули и
единицы) при помощи компилятора с применением разнообразных
флагов и параметров. Когда вы запускаете такую программу,
429
2018 Ren’Py
6.Объектно-ориентированный
Python поддерживает как процедурно-ориентированное, так и
объектно-
ориентированное программирование. В процедурно-
ориентированных языках программы строятся на основе процедур
или функций, которые представляют собой просто-напросто
многократно используемые фрагменты программы. В объектно-
ориентированных языках программирования программы строятся на
основе объектов, объединяющих в себе данные и функционал. Python
предоставляет простые, но мощные средства для ООП, особенно в
сравнении с такими большими языками программирования, как C++
или Java.
7.Расширяемый
Если вам нужно, чтобы некоторая критическая часть программы
работала очень быстро или вы вынуждены скрыть часть алгоритма,
вы можете написать эту часть программы на C или C++, а затем
вызывать её из программы на Python.
8. Встраиваемый
Python можно встраивать в программы на C/C++, чтобы предоставлять
возможности на писания сценариев их пользователям.
9. Обширные библиотеки
Стандартная библиотека Python просто огромна. Она может помочь в
решении самых разнообразных задач, связанных с использованием
регулярных выражений, генерированием документации, проверкой
блоков кода, распараллеливанием процессов, базами данных, веб-
браузерами, CGI, FTP, электронной почтой, XML, XML-RPC, HTML,
WAV файлами, криптографией, GUI (графическим интерфейсом
430
2018 Ren’Py
СТИЛЬ ПРОГРАММИРОВАНИЯ
РЕКОМЕНДАЦИИ ПО СТИЛЮ
431
2018 Ren’Py
ОТСТУПЫ
432
2018 Ren’Py
ПУСТЫЕ СТРОКИ
Другие рекомендации
PEP 8 содержит много других рекомендаций по стилю, но эти
рекомендации в основном относятся к программам более сложным,
чем те, которые вы пишете на данный момент. По мере изучения
более сложных возможностей Python я буду приводить
соответствующие фрагменты рекомендаций PEP 8.
433
2018 Ren’Py
init:
label start:
$ gul = True
$ money = 0
И еще как пример(именно его и рекомендую если больше 1
переменной требуется указать, так как у $ минус, каждую строку
придется со знаком доллара прописывать)
label start:
python:
n=0
n1 = 0
money = 0
434
2018 Ren’Py
normani = False
vostok = False
kiev = False
doom = 0
db = 0
И их пишут обычно сразу в метке start что бы избежать многих ошибок,
которые возникают из за того, что ренпай не видит нужную вам
переменную.
init:
first_name = 'Безымянный!t'
input_first_name = 'Иван!t'
input_last_name = 'Иванов!t'
label start:
….
435
2018 Ren’Py
436
2018 Ren’Py
437
2018 Ren’Py
'str';
y = 'str'; x == y даёт
True.
!= Не равно Проверяет, верно ли, x = 2; y = 3; x != y даёт
что объекты не равны True.
not Логическое НЕ Если x равно True, x = True; not x даёт
оператор вернёт False. False.
Если же x равно
False, получим True.
and Логическое И x and y даёт False, x = False; y = True; x
если x равно False , в and
противном случае y возвращает False,
возвращает значение y поскольку
x равно False. В этом
случае Python не
станет проверять
значение y, так как уже
знает, что левая часть
выражения ‘and’
равняется False, что
подразумевает, что и
всё выражение в
целом будет
равно False,
независимо от
значений всех
остальных
операндов. Это
называется
укороченной оценкой
булевых (логических)
выражений.
or Логическое ИЛИ Если x равно True, в x = True; y = False; x or
результате получим y
True, в противном даёт True. Здесь также
случае получим может
значение y производиться
укороченная оценка
выражений.
438
2018 Ren’Py
4) умножаем
$ sila = 10
$ ves = 5*ves
"[ves]"
получим 50 веса, но так никто не делает на рпг – ошибки будут
5) делим
$ zashita = 10
$ uron = 2/zashita
"[uron]"
получим 5 урона, но так никто не делает на рпг – ошибки будут
НО обратите внимание!
$ zashita = 2
$ uron = 3/zashita
"[uron]"
Получите 1. Результатом деления целых чисел в Python 2 становится целое
число с потерей остатка. Обратите внимание: результат не округляется,
просто остаток от деления пропадает.
439
2018 Ren’Py
$ zakaz = 'Компот'
"Я заказал пиво"
"А привезли [zakaz]"
if zakaz != 'Пиво':
"Я пиво заказывал а не [zakaz]!!!"
7) Устанавливаем степень
$ sila = 10 ** 2
"[sila]"
Получим 100
8) Устанавливаем порядок выполнения скобки
$ sila = 20+(10-5 * 2)
Устанавливаем значение
1) $ rep = 10 и $ rep = -100 – Значение переменной будет равна 10 и -
100, т.е. допустим у персонажа 10 отношений, он украл что то и
отношение сразу стали равны -100
2) $ wolf_hp = wolf_max_hp – значение 1 переменной равна значению
другой
Условие
1) if mmo – При значении True
2) elif mmo == 1 - При точном значении 1
3) if mmo >= 1 или if mmo <= 1 - при равном или большем значении 1
или наоборот
4) if mmo >1 или if mmo < 1 - Если больше 1 или меньше
441
2018 Ren’Py
jump den_2
label den_2:
if gul:
"Катя" "Классно мы вчера с компанией погуляли))) Почаще
выходи с нами )"
else:
"Катя" "Мы вчера так весело погуляли!!! Жалко тебя не было…"
"Учитель" "Показываем ваши домашние задания"
if gul:
"Катя" "Упс…."
"Катя" " Ты тоже спать после прогулки лег?"
else:
"Катя" "Дай списать!!!!! ПОЖАЛУСТА!!!!!"
"Катя" " Ты то точно написал ее!!!"
Разберем, что тут мы записали
После выбора гулять или нет, мы видим после метки значение $ gul =
True.
Значком $ в начале помечают коды питона, переменные. Делаем
такой же отступ, как и на обычный диалог,
$ gul – так мы назвали переменную, а ее логическое выражение True
или False т.е. мы можем так же и цифры, и буквенно-цифровые
значения прописать, самое главное не забыть как вы их записали. И
что бы не было ошибки, вам нужно сделать прыжок к другой
метке(jump den_2), т.к. если после выбора значение флага (=) не
сделать этого - оно примет то условие что будет записано в
следующей метке.
После того как вы сделали выбор, у вас переменная приняла свое
значение (= ) , потом на следующий день включается проверка
переменной (if gul: ) если переменная включена (True) то произойдет
событие которое должно произойти при включенной переменной.
Если нужно значение переменной любое другое кроме тех, что были
442
2018 Ren’Py
ЧИСЛОВОЕ ЗНАЧЕНИЕ
До этого мы рассматривали, как прописать флаги, теперь мы
рассмотрим значения числовые.
label start:
$ gul = 0
"Ты будешь гулять сегодня?"
menu:
"Да":
$ gul +=1
jump da_gul
"Нет":
jump net_gul
label da_gul:
"Катя" "Хорошо ждем тебя на улице"
"Во время прогулки ты ее поцелуешь?"
menu:
"Да":
$ gul +=1
443
2018 Ren’Py
"ок"
"Нет":
"ок"
jump den_2
label net_gul:
"Катя" "Жалко… Тогда до завтра"
jump den_2
label den_2:
if gul ==1:
"Катя" "Классно мы вчера с компанией погуляли))) Почаще
выходи в белый свет)
elif gul >1:
"Девушка покраснела когда встретилась взглядом с тобой"
else:
"Катя" "Мы вчера так весело погуляли!!! Жалко тебя не было…"
"Учитель" "Показываем ваши домашние задания"
if gul ==1:
"Катя" "Упс…."
elif gul >1:
"Катя" "*шепотом* Какие блин уроки после вчерашнего...."
else:
"Катя" "Дай списать!!!!! ПОЖАЛУСТА!!!!!"
"Катя" " Ты то точно написал ее!!!"
444
2018 Ren’Py
или нет гулять, и пропишем, поцелует он ее($ gul +=1) или нет.
символ =+ обозначает что мы к переменной прибавляем ее значение,
а 1 знак равно будет значить что переменная приняла такое
значение. В отличии от фагов в числах можно кучу событий прописать
и развязок…. и фагами в принципе можно, но это куча лишних
переменных, и еще бы их всех запомнить. А в числовых переменных
можно кучу условий прописать для скрытой концовки всего 1
переменной.
Далее на следующий день у нас должна произойти развязка после
событий.
Что бы заработало по выбранным условиям, нам необходимо
прописать эти условия.
Опять обращаю внимание на фразу "Учитель" "Показываем ваши
домашние задания" она на таком же уровне пишется, как и все
остальные условия
if gul ==1: - Если мы пошли, но не поцеловались, что бы система
прочитала правильно-точное значение то пишут знак = два раза( = =
)
elif gul >1: - Если нужно прописать еще одно возможное событие то
его необходимо записать в elif, и что бы его значение было больше 1
то пишут >1: (больше 1) или пишут (равен или больше 2) =>2: или
(точное значение) ==2
else: - Если не совпадает с предыдущими событиями
445
2018 Ren’Py
446
2018 Ren’Py
label start:
447
2018 Ren’Py
python:
name = "серж горелый."
message = name.title() ###Заглавные буквы
message1 = name.upper() ###Все большое
message2 = name.lower() ###Все маленькое
"[message]"
"[message1]"
"[message2]"
Программа выводит следующий результат:
Серж Горелый
СЕРЖ ГОРЕЛЫЙ
серж горелый
Метод lower() особенно полезен для хранения данных. Нередко
программист не может рассчитывать на то, что пользователи введут
все данные с точным соблюдением регистра, поэтому строки перед
сохранением преобразуются к нижнему регистру. Затем, когда
потребуется вывести информацию, используется регистр, наиболее
подходящий для каждой строки.
КОНКАТЕНАЦИЯ. ОБЪЕДИНЕНИЕ
ПЕРЕМЕННЫХ
Также часто возникает необходимость в объединении строк.
Представьте, что имя и фамилия хранятся в разных переменных, и вы
хотите объединить их для вывода полного имени. Для объединения
строк в Python используется знак «плюс» (+).
label start:
python:
name = "серж"
448
2018 Ren’Py
family = "горелый"
ger = name + " " + family
message = ger.title()
"[message]"
Такой способ объединения строк называется конкатенацией. Вы
можете использовать конкатенацию для построения сложных
сообщений с информацией, хранящейся в переменных.
name2 = "Меня зовут - " + name.title() + " .Очень приятно
познакомиться."
УДАЛЕНИЕ ПРОПУСКОВ
Лишние пропуски могут вызвать путаницу в программах. Для
программиста строки 'python' и 'python ' внешне неотличимы, но для
программы это совершенно разные строки. Python видит лишний
пробел в 'python ' и считает, что он действительно важен — до тех пор,
пока вы не сообщите о противоположном.
Обращайте внимание на пропуски, потому что в программах часто
приходится сравнивать строки, чтобы проверить на совпадение их
содержимое. Типичный пример — проверка имен пользователей при
входе на сайт. Лишние пропуски могут создавать путаницу и в более
простых ситуациях. К счастью, Python позволяет легко удалить
лишние пропуски из данных, введенных пользователем.
Python может искать лишние пропуски у левого и правого края строки.
Чтобы убедиться в том, что у правого края (в конце) строки нет
пропусков, вызовите метод rstrip().
label start:
python:
name = "python "
message = name.rstrip().
"[message]"
И получим текст
449
2018 Ren’Py
python
Операция изменения значения переменной с последующим его
сохранением в исходной переменной часто выполняется в
программировании. Так значение переменной может изменяться в
ходе выполнения программы или в ответ на действия пользователя.
Пропуски также можно удалить у левого края (в начале) строки при
помощи метода lstrip(), а метод strip() удаляет пропуски с обоих
концов
Поэкспериментируйте с функциями удаления пропусков, это поможет
вам освоиться с работой со строками. На практике эти функции чаще
всего применяются для «очистки» пользовательского ввода перед его
сохранением в программе.
СПИСКИ
450
2018 Ren’Py
grid 1 1:
frame:
vbox:
text "Мой список блюд:"
vbox:
for my_food in my_foods:
text "[my_food]"
label start:
window hide
python:
my_foods = ['Пицца', 'Маккароны', 'Тортик']
show screen for_screen
pause
Сохраните и запустите проект.
451
2018 Ren’Py
vbox:
text "Мой список блюд:"
vbox:
for my_food in my_foods:
text "[my_food]"
label start:
window hide
python:
my_foods = ['Пицца', 'Маккароны', 'Тортик']
show screen for_screen
pause
hide screen for_screen
"Надеюсь никто не откажется от [my_foods[0]]"
pause
У вас высветится пицца в тексте
$ re =my_foods[0].title() – что бы оно было с заглавной буквы
$ mi = "Ты будешь" + my_foods[0].title() + "?"
или
$ mi = "Ты будешь [re]?"
452
2018 Ren’Py
453
2018 Ren’Py
label start:
window hide
python:
my_foods = ['Пицца', 'Маккароны', 'Тортик']
show screen for_screen
pause
python:
my_foods[0] = 'Шашлык'
pause
Изменить можно значение любого элемента в списке, не только
первого.
Пицца Маккароны Тортик###до
Шашлык Маккароны Тортик ###после
454
2018 Ren’Py
grid 1 1:
frame:
vbox:
text "Мой список блюд:"
vbox:
for my_food in my_foods:
text "[my_food]"
label start:
window hide
python:
my_foods = ['Пицца', 'Маккароны', 'Тортик']
show screen for_screen
pause
python:
my_foods.append('Шашлык')
pause
Получим
Пицца Маккароны Тортик ###до
Пицца Маккароны Тортик Шашлык ###после
Метод append() упрощает динамическое построение списков.
Например, вы можете начать с пустого списка и добавлять в него
элементы серией команд append(). В следующем примере в пустой
список добавляются элементы блюд:
label start:
window hide
python:
my_foods = [ ]
455
2018 Ren’Py
456
2018 Ren’Py
УДАЛЕНИЕ ЭЛЕМЕНТА С
ИСПОЛЬЗОВАНИЕМ КОМАНДЫ DEL
Если вам известна позиция элемента, который должен быть удален из
списка, воспользуйтесь командой del.
label start:
window hide
python:
my_foods = ['Пицца', 'Маккароны', 'Тортик']
show screen for_screen
pause
python:
del my_foods[0]
pause
УДАЛЕНИЕ ЭЛЕМЕНТА С
ИСПОЛЬЗОВАНИЕМ МЕТОДА POP()
Метод pop() удаляет последний элемент из списка, но позволяет
работать с ним после удаления.
screen for_screen():
frame:
457
2018 Ren’Py
label start:
window hide
python:
my_foods = ['Пицца', 'Маккароны', 'Тортик']
show screen for_screen
python:
popped_my_foods = my_foods.pop()
pause
Получаем
Пицца Маккароны Тортик #до
Пицца Маккароны #после
Для чего может понадобиться метод pop()? Представьте, что
мотоциклы в списке хранятся в хронологическом порядке в
соответствии с датой их покупки. В таком случае команда pop() может
использоваться для вывода сообщения о последнем купленном
мотоцикле:
label start:
458
2018 Ren’Py
python:
motorcycle = ['honda', 'yamaha', 'suzuki']
last_owned = motorcycle.pop()
"Список оставшихся мотоциклов"
"[motorcycle]"
"До этого у нас был продан [last_owned]"
ИЗВЛЕЧЕНИЕ ЭЛЕМЕНТОВ ИЗ
ПРОИЗВОЛЬНОЙ ПОЗИЦИИ СПИСКА
Вызов pop() может использоваться для удаления элемента в
произвольной позиции списка; для этого следует указать индекс
удаляемого элемента в круглых скобках.
label start:
python:
motorcycle = ['honda', 'yamaha', 'suzuki']
last_owned = motorcycle.pop(0) ### 0 в скобках
"Список оставшихся мотоциклов"
"[motorcycle]"
"До этого у нас был продан [last_owned]"
Если вы не уверены в том, какой из двух способов выбрать — команду
del или метод pop(), — то простое правило поможет вам определиться.
Если вы собираетесь просто удалить элемент из списка, никак не
используя его, выбирайте команду del; если же вы намерены
использовать элемент после удаления из списка, выбирайте метод
pop().
459
2018 Ren’Py
label start:
python:
motorcycle = ['honda', 'yamaha', 'suzuki', 'ducati']
motorcycles.remove('ducati')
460
2018 Ren’Py
461
2018 Ren’Py
ПОДРОБНЕЕ О ЦИКЛАХ
Концепция циклов очень важна, потому что она представляет один из
основных способов автоматизации повторяющихся задач
462
2018 Ren’Py
"[magician]"
"[magician]"
463
2018 Ren’Py
ГЕНЕРАТОР СПИСОК
464
2018 Ren’Py
frame:
xalign 0.5 ypos 50
vbox:
for square in squares:
text "[square] денег"
label start:
show screen for_screen
pause
Чтобы использовать этот синтаксис, начните с содержательного
имени списка, например squares. Затем откройте квадратные скобки и
определите выражение для значений, которые должны быть
сохранены в новом списке. В данном примере это выражение value**2,
которое возводит значение во вторую степень. Затем напишите цикл
for для генерирования чисел, которые должны передаваться вы-
ражению, и закройте квадратные скобки. Цикл for в данном примере —
for value in range(1,11) — передает значения с 1 до 10 выражению
value**2. Обратите внимание на отсутствие двоеточия в конце
команды for.
Результатом будет уже знакомый вам список квадратов:
СОЗДАНИЕ СРЕЗА
465
2018 Ren’Py
466
2018 Ren’Py
python:
players = ['charles', 'martina', 'michael', 'florence', 'eli']
player2 = players[:4]
"[player2]"
pause
Без начального индекса Python берет элементы от начала списка:
467
2018 Ren’Py
player2 = players[-3:]
"[player2]"
pause
Программа выводит имена трех последних игроков, причем
продолжает работать даже при изменении размера списка.
label start:
$ players = ['Charles', 'Martina', 'Michael', 'Florence', 'Eli']
show screen for_screen
pause
КОПИРОВАНИЕ СПИСКА
468
2018 Ren’Py
label start:
python:
my_foods = ['pizza', 'falafel', 'carrot cake']
friend_foods = my_foods[:]
469
2018 Ren’Py
label start:
window hide
python:
my_foods = ['pizza', 'falafel', 'carrot cake']
470
2018 Ren’Py
friend_foods = my_foods[:]
show screen for_screen
pause
"Разные блюда добавим"
window hide
python:
my_foods.append('cannoli')
friend_foods.append('ice cream')
pause
СЛОВАРИ
ПРОСТОЙ СЛОВАРЬ
screen for_screen():
frame:
xalign 0.5 yalign 0.5
background None
grid 1 1:
471
2018 Ren’Py
frame:
vbox:
text "Мой список блюд:"
vbox:
text "Блюдо: [my_foods[Блюдо]]"
text "Порции: [my_foods[Порции]]"
label start:
window hide
python:
my_foods = {'Блюдо': 'Пицца', 'Порции':1}
show screen for_screen
pause
В словаре my_foods хранятся два атрибута: блюдо и количество
порций Следующие две команды "[my_foods[Блюдо]]" и
"[my_foods[Порции]]" читают эту информацию из словаря и выводят
ее на экран:
РАБОТА СО СЛОВАРЯМИ
472
2018 Ren’Py
473
2018 Ren’Py
label start:
$ aes = 0
window hide
python:
my_foods = {'Блюдо': 'Пицца', 'Порции':1}
show screen for_screen
pause
$ aes = 1
$ my_foods['Гостей'] = 2 # Добавляем новую пару в словарь
pause
474
2018 Ren’Py
label start:
$ aes = 0
$ my_foods = { }
show screen for_screen
"Что будем гостям накрывать?"
$ aes = 1
$ my_foods['Блюдо'] = 'Шашлык'
"А сколько порций?"
475
2018 Ren’Py
$ aes = 2
$ my_foods['Порции'] = 2
$ aes = 3
$ my_foods['Гостей'] = 2
"А гостей сколько будет?"
pause
label start:
$ my_foods = {'Блюдо': 'Пицца'} #значение пицца
show screen for_screen
476
2018 Ren’Py
"Подать пиццу?"
$ my_foods['Блюдо'] = 'Шашлык' #меняем на шашлык
"Или шашлыка пожарить?"
pause
477
2018 Ren’Py
window hide
$ aes = 1
python:
my_foods = {'Блюдо': 'Пицца', 'Порции':1}
show screen for_screen
pause
$ del my_foods['Порции']
$ aes = 2
pause
478
2018 Ren’Py
label start:
$ favorite_languages = {
'jen': 'python',
'sarah': 'c',
'edward': 'ruby',
'phil': 'python',
}
show screen for_screen
pause
Пары в словаре в этой записи разбиты по строкам. Ключами являются
имена участников опроса, а значениями — выбранные ими языки.
Если вы знаете, что для определения словаря потребуется более
одной строки, нажмите клавишу Enter после ввода открывающей
фигурной скобки. Снабдите следующую строку отступом на один
уровень (четыре пробела) и запишите первую пару «ключ—значение»,
поставив за ней запятую. После этого при нажатии Enter ваш
текстовый редактор будет автоматически снабжать все последующие
пары таким же отступом, как у первой.
Завершив определение словаря, добавьте закрывающую фигурную
скобку в новой строке после последней пары «ключ—значение» и
снабдите ее отступом на один уровень, чтобы она была выровнена по
ключам. За последней парой также рекомендуется включить запятую,
чтобы при необходимости все было готово к добавлению новой пары
«ключ—значение» в следующей строке.
479
2018 Ren’Py
480
2018 Ren’Py
481
2018 Ren’Py
label start:
$ favorite_languages = {
'jen': 'python',
'sarah': 'c',
'edward': 'ruby',
'phil': 'python',
}
show screen for_screen
pause
Код
for name, language in favorite_languages.items():
приказывает Python перебрать все пары «ключ—значение» в словаре.
В процессе перебора пар ключ сохраняется в переменной name, а
значение — в переменной language. С этими содержательными
именами намного проще понять, что делает команда
text "\nУ " +name.title() + " любимый язык програмирования " +
language.title() + "."
Всего в нескольких строках кода выводится вся информация из опроса
.
Такой способ перебора точно так же работает и в том случае, если в
словаре будут храниться результаты опроса тысяч и даже миллионов
людей.
482
2018 Ren’Py
483
2018 Ren’Py
screen for_screen():
frame:
xalign 0.5 yalign 0.5
background None
grid 1 1:
frame:
vbox:
text "Люди которые принимали участие в опросе:"
vbox:
for name, language in favorite_languages.items():
text "\n" + name.title()
if name in friends:
text "А " + name.title() + ", мой друг и он любит " +
favorite_languages[name].title() + "!"
label start:
$ favorite_languages = {
'jen': 'python',
'sarah': 'c',
'edward': 'ruby',
'phil': 'python',
}
$ friends = ['phil', 'sarah']
484
2018 Ren’Py
pause
Метод keys() также может использоваться для проверки того,
участвовал ли конкретный человек в опросе:
screen for_screen():
frame:
xalign 0.5 yalign 0.5
background None
grid 1 1:
frame:
vbox:
text "Люди которые принимали участие в опросе:"
vbox:
for name, language in favorite_languages.items():
text "\n" + name.title()
if name in friends:
text "А " + name.title() + ", мой друг и он любит " +
favorite_languages[name].title() + "!"
if 'erin' not in favorite_languages.items():
text "Erin, не прошла тест!"
label start:
$ favorite_languages = {
'jen': 'python',
'sarah': 'c',
'edward': 'ruby',
'phil': 'python',
}
485
2018 Ren’Py
486
2018 Ren’Py
background None
grid 1 1:
frame:
vbox:
text "Какие языки были в опросе:"
vbox:
for language in favorite_languages.values():
text language.title()
label start:
$ favorite_languages = {
'jen': 'python',
'sarah': 'c',
'edward': 'ruby',
'phil': 'python',
}
488
2018 Ren’Py
frame:
xalign 0.5 yalign 0.5
background None
grid 1 1:
frame:
vbox:
text "Какие языки были в опросе:"
vbox:
for language in set(favorite_languages.values()):
text language.title()
label start:
$ favorite_languages = {
'jen': 'python',
'sarah': 'c',
'edward': 'ruby',
'phil': 'python',
}
СПИСОК В СЛОВАРЕ
489
2018 Ren’Py
label start:
$ pizza = {
'crust': 'Обед',
'toppings': ['Сыр', 'Помидоры'],
}
490
2018 Ren’Py
}
show screen for_screen
pause
Вы видите что значение, связанное с каждым именем, теперь
представляет собой список. У некоторых участников только один
любимый язык программирования, у других таких языков несколько.
При переборе словаря переменная с именем languages используется
для хранения каждого значения из словаря, потому что мы знаем, что
каждое значение будет представлять собой список. В основном цикле
по элементам словаря другой цикл перебирает элементы списка
любимых языков каждого участника.
Теперь каждый участник опроса может указать сколько угодно
любимых языков программирования
СЛОВАРЬ В СЛОВАРЕ
screen for_screen():
frame:
xalign 0.5 yalign 0.5
background None
grid 1 1:
frame:
vbox:
492
2018 Ren’Py
label start:
$ users = {
'aeinstein': {
'first': 'Сергей',
'last': 'Романов',
'location': 'Москва',
},
'mcurie': {
'first': 'Анастасия',
'last': 'Тяпченко',
'location': 'Сочи',
},
}
493
2018 Ren’Py
ЦИКЛЫ WHILE
494
2018 Ren’Py
screen for_screen():
frame:
xalign 0.5 ypos 50
vbox:
if message != 'quit':
text "[message]"
else:
text "Все верно"
label start:
$ message = " "
show screen for_screen
$ prompt = "\nВведите команду:"
while message != 'quit':
$ message = renpy.input(prompt)
"\nНажмите quit Что бы закрыть цикл"
"Конец"
pause
ФЛАГИ
496
2018 Ren’Py
497
2018 Ren’Py
498
2018 Ren’Py
text confirmed_user.title()
frame:
vbox:
text "Список не провереных пользователей"
for unconfirmed_user in unconfirmed_users:
text unconfirmed_user.title()
# Начинаем с двух списков: пользователей для проверки
# и пустого списка для хранения проверенных пользователей.
label start:
show screen for_screen
$ unconfirmed_users = ['alice', 'brian', 'candace']
$ confirmed_users = []
"Начать проверку"
# Проверяем каждого пользователя, пока остаются непроверенные
# пользователи. Каждый пользователь, прошедший проверку,
# перемещается в список проверенных.
while unconfirmed_users:
""
$ current_user = unconfirmed_users.pop()
"Проверка пользователя: [current_user]"
$ confirmed_users.append(current_user)
# Вывод всех проверенных пользователей.
$ ser = current_user.title()
"\nПользователь [ser] подтвержден"
"Список окончен"
pause
499
2018 Ren’Py
label start:
500
2018 Ren’Py
pause
501
2018 Ren’Py
$ polling_active = True
"Начать анкетирование"
show screen for_screen
pause
python:
while polling_active:
name = renpy.input("\nКак тебя зовут? ")
response = renpy.input("Ты какой язык учил в школе? ")
responses[name] = response
repeats = renpy.input("Хочешь добавить еще анкету? (yes/ no) ")
if repeats == 'no':
polling_active = False
ФУНКЦИИ
502
2018 Ren’Py
ОПРЕДЕЛЕНИЕ ФУНКЦИИ
screen for_screen():
frame:
background None
xalign 0.5 yalign 0.5
grid 1 1:
frame:
vbox:
text "[musician]"
label start:
$ musician = get_formatt('Вася', 'Пупкин') # 6 строка
show screen for_screen
pause
Разберем что мы тут записали:
Строка 1 – обьявляем функцию в питоне, инит требуется для
определения кода до начала запуска проекта
Строка 2 при помощи ключевого слова def сообщает Python, что вы
определяете функцию. В определении функции указывается имя
503
2018 Ren’Py
НЕОБЯЗАТЕЛЬНЫЕ АРГУМЕНТЫ
init python:
def get_formatt(first_name, middle_name, last_name):
504
2018 Ren’Py
screen for_screen():
frame:
background None
xalign 0.5 yalign 0.5
grid 1 1:
frame:
vbox:
for musicians in musician:
text "[musicians]"
label start:
$ musician = get_formatt('john', 'lee', 'hooker')
show screen for_screen
pause
Функция работает при получении имени, второго имени и фамилии.
Она получает все три части имени, а затем строит из них строку.
Функция добавляет пробелы там, где это уместно, и преобразует
полное имя в формат с капитализацией
Однако вторые имена нужны не всегда, а в такой записи функция не
будет работать, если при вызове ей передаются только имя и
фамилия. Чтобы средний аргумент был необязательным, можно
присвоить аргументу middle_name пустое значение по умолчанию;
этот аргумент игнорируется, если пользователь не передал для него
значение. Чтобы функция get_formatt() работала без второго
имени, следует назначить для параметра middle_name пустую строку
значением по умолчанию и переместить его в конец списка
параметров:
505
2018 Ren’Py
init python:
def get_formatt(first_name, last_name, middle_name= ' ' ):
"""Возвращает аккуратно отформатированное полное имя."""
if middle_name:
full_name = first_name + ' ' + middle_name + ' ' + last_name
else:
full_name = first_name + ' ' + last_name
return full_name.title()
screen for_screen():
frame:
background None
xalign 0.5 yalign 0.5
grid 1 1:
frame:
vbox:
text "[musician]"
label start:
$ musician = get_formatt('john', 'lee')
show screen for_screen
pause
$ musician = get_formatt('john', 'lee', 'hooker')
pause
В этом примере имя строится из трех возможных частей. Поскольку
имя и фамилия указываются всегда, эти параметры стоят в начале
списка в определении функции. Второе имя не обязательно, поэтому
оно находится на последнем месте в определении, а его значением по
умолчанию является пустая строка.
506
2018 Ren’Py
ВОЗВРАЩЕНИЕ СЛОВАРЯ
init python:
def build_person(first_name, last_name):
507
2018 Ren’Py
label start:
$ musician = build_person('Эдди', 'Мерфи') #3
show screen for_screen
pause
Функция build_person() получает имя и фамилию и сохраняет
полученные значения в словаре в точке . Значение first_name
сохраняется с ключом 'Имя', а значение last_name — с ключом
'Фамилия'. Весь словарь с описанием человека возвращается в точке
. Возвращаемое значение выводится в точке с двумя исходными
фрагментами текстовой информации, теперь хранящимися в словаре
Функция получает простую текстовую информацию и помещает ее в
более удобную структуру данных, которая позволяет работать с
информацией (помимо простого вывода). Строки 'Эдди' и 'Мерфи'
теперь помечены как имя и фамилия. Функцию можно легко
расширить так, чтобы она принимала дополнительные значения: —
508
2018 Ren’Py
509
2018 Ren’Py
screen for_screen():
frame:
background None
xalign 0.5 yalign 0.5
grid 1 1:
frame:
vbox:
text "\nHello, " + formatted_name + "!"
label start:
$ formatted_name = " "
510
2018 Ren’Py
$ f_name = ""
$ l_name = ""
show screen for_screen
python:
while True:
formatted_name = get_formatted_name(f_name, l_name)
f_name = renpy.input("First name: ")
l_name = renpy.input("Last name: ")
pause
В этом примере используется простая версия get_formatted_name(),
без вторых имен. В цикле while имя и фамилия пользователя
запрашиваются по отдельности.
511
2018 Ren’Py
frame:
vbox:
text "Печатается модель: " + current_design
frame:
vbox:
for completed_model in completed_models:
text "Готовые модели " + completed_model
label start:
python:
completed_models = []
unprinted_designs = ['iphone case', 'robot pendant', 'dodecahedron']
current_design = " "
show screen for_screen
"Начало"
while unprinted_designs:
$ current_design = unprinted_designs.pop()
"Готово"
$ completed_models.append(current_design)
pause
В начале программы создается список моделей и пустой список
completed_models, в который каждая модель перемещается после
печати. Пока в unprinted_designs остаются модели, цикл while
имитирует печать каждой модели: модель удаляется с конца списка,
сохраняется в current_design, а пользователь получает сообщение о
том, что текущая модель была напечатана. Затем модель
перемещается в список напечатанных. После завершения цикла
выводится список напечатанных моделей
512
2018 Ren’Py
screen for_screen():
frame:
background None
xalign 0.5 yalign 0.5
grid 1 1:
hbox:
frame:
vbox:
text "Печатается модель: " + current_design
frame:
vbox:
for completed_model in completed_models:
513
2018 Ren’Py
label start:
python:
completed_models = []
unprinted_designs = ['iphone case', 'robot pendant', 'dodecahedron']
current_design = " "
pause
514
2018 Ren’Py
https://patchydollgames.itch.io/yourswimsuit
515
2018 Ren’Py
class Markov(object):
def file_to_words(self):
self.open_file.seek(0)
data = self.open_file.read()
words = data.split()
return words
def triples(self):
""" Generates triples from the given data string. So if our string
were
"What a lovely day", we'd generate (What, a, lovely) and then
(a, lovely, day).
"""
if len(self.words) < 3:
return
def database(self):
516
2018 Ren’Py
effectGen = 0 #
effectA = 0 # Использовать для рандомизации моддинга переменной типа
effectB = 0 # в меню выбора.
effectC = 0 # (различный путь «победить» каждый раз)
517
2018 Ren’Py
"%(mString)s"
return
label Gen: # генерирует серию из трех строк для параметров меню, не вызывайте
напрямую
$ mStringA = markovC.generate_markov_text()
$ mStringB = markovC.generate_markov_text()
$ mStringC = markovC.generate_markov_text()
return
if (effectGen == 0):
effectA = -1
effectGen = renpy.random.randint(0,1)
if (effectGen == 0):
effectB = 0
effectC = 1
else:
effectC = 0
effectB = 1
effectGen = renpy.random.randint(0,1)
if (effectGen == 0):
effectA = 0
effectC = 1
else:
effectC = 0
effectA = 1
effectGen = renpy.random.randint(0,1)
if (effectGen == 0):
effectA = 0
effectB = 1
else:
effectB = 0
effectA = 1
518
2018 Ren’Py
call Nsay
call Nsay
show m
with dissolve
call Msay
call Msay
call Ysay
m "..."
call Nsay
call Nsay
call Msay
call MenuTwo
# the menu modified the "like" variable, so let's change the story branch
based on its new value
if like > 0:
519
2018 Ren’Py
jump branch1
else:
jump branch2
Там вы идете! Случайный текст, случайные опции меню, случайные результаты. Это
действительно простой , но результат может быть очень весело.
Для начало посмотрим на код который мы хотим портировать (Это будет звездное
небо которое двигается)
#!/usr/bin/python
TOTAL_STARS = 500
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
class Star(object):
color = [0,0,0]
position = [0,0]
speed = 1
def __init__(self):
self.generateStartPosition(xrandom=True)
def update(self):
self.position[0] -= self.speed
if(self.position[0] < 0):
# generate new star
self.generateStartPosition()
520
2018 Ren’Py
xpos = int(self.position[0])
ypos = int(self.position[1])
screen.fill(self.color, pygame.Rect(xpos, ypos, 1, 1))
def setup():
pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
return(screen)
def checkEvents():
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
# or exit on spacebar being pressed
if event.type == pygame.KEYDOWN:
if event.key == 32:
sys.exit()
def loop(screen):
stars = [Star() for x in range(TOTAL_STARS)]
while(True):
screen.fill([0,0,0])
for star in stars:
star.draw(screen)
star.update()
pygame.display.flip()
checkEvents()
if __name__ == '__main__':
screen = setup()
loop(screen)
Если у вас есть установленный питон и Pygame запустите этот код в них, и вы
увидите красивые звезды
Теперь нам необходимо портировать в Renpy этот код. Нам нужно сделать так,
что бы пользователь мог его в любой момент отобразить в своем проекте.
label start:
"Тут начнется звездопад"
return
521
2018 Ren’Py
Далее нам нужно создать новый файл сценария в проекте (назовем его star.rpy)
И прописать в нем код, который показывал бы ренпаю что это код питона
init -1 python:
init -1 python:
# и разрешения(константы)
TOTAL_STARS = 500
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
def __init__(self):
self.generateStartPosition(xrandom=True)
def update(self):
self.position[0] -= self.speed
if(self.position[0] < 0):
# генерируем новые звезды
self.generateStartPosition()
522
2018 Ren’Py
def visit(self):
"""Эта функция должна вернуть все displayables.
У нас их нет, так что просто верните пустой список"""
return []
label start:
# теперь нам нужно добавить экран в фон проекта
show screen star_screen
"Тут начнется звездопад"
https://pp.userapi.com/c834103/v834103718/10ef1e/1I_6PsZdNbY.jpg
Как вы могли заметить версия Renpy медленнее , чем оригинальный Python. Это связано
со многими факторами, главным из которых , что Renpy делает другие вещи в фоновом
режиме (например, наложение текста)
523
2018 Ren’Py
Идея заключается в том , что иногда вы хотите знать , какой выбор , тестеры , сделали во
время игры, и дать им легкий способ высказаться
Создайте отдельный файл и запишите измененный как вам нужно следующий код:
init python:
import pickle
with open(os.path.join(config.renpy_base, "feedback.txt"), "w") as
file:
pickle.dump(s, file)
# Эта часть объединяет всю информацию, которая будет сохранена в текстовом файле.
label generate_feedback_file:
$ feedback = str("Имя главного героя:" + mcs_name + " " + mcs_surname + ".\
n\ Они являются"
+ mcs_gender + ", и " + mc_he_or_she + " в " + mcs_city + " в " +
mcs_country + ".\n\ Игрок взял"
+ str(time_taken_to_choose_gender_in_minutes) + " минут и сек " +
str(time_taken_to_choose_gender_in_seconds) + " секунд, чтобы выбрать пол героя.\
n\ "
+ str(mcs_initial_feelings_about_the_first_invitation_to_japan) + ".\n\ "
+ what_did_the_mc_tell_dave_about_their_japanese_ability + ".")
$ create_feedback(feedback)
infodump "[feedback]"
return
524
2018 Ren’Py
приглашены в Японию"
$ what_did_the_mc_tell_dave_about_their_japanese_ability = "Они еще не встретили
Дейва"
http://greentarga.ucoz.ru/publ/a/primery_koda/dobavljaem_sqlite3_i_berkeleydb_v_renpy/5-1-0-
46
525
2018 Ren’Py
СОЗДАЕМ ИНСТАЛЛЯТОР
Когда вы закончили свою демо, или проект. Вам потребуется создать
инсталлятор (дабы серьезней выглядело все, и не знающие ренпай
могли поиграть в ваш проект.)
1) Для этого, заходим в лаунчер ренпая,
2) Выбираем раздел «очистить постоянные данные». Дабы у игрока
сразу не было все открыто, и он ваш проект пропуском за 5 мин не
прошел.
3) Выбираем пункт «Построить дистрибьютор» И там выбираем что
вы хотите сделать(на виндовс или линукс и т.д) и программа
автоматом создаст ехе и т.д.
4) Выходим на папку проекта test(где вы построили дистрибьютор)
или какой вы создавали. Далее вы щелкаете правой кнопкой мыши на
ваш проект и выбираете создать архив(winrar), выскакивает окошко и
выделяете галкой Создать SFX-архив
526
2018 Ren’Py
ПОРТИРУЕМ АНДРОИД
527
2018 Ren’Py
529
2018 Ren’Py
Вам потребуется зайти в папку где у вас находится лаунчер ренпая и найти папку
ПОРТИРУЕМ НА АЙФОН
В лаунчере ренпая нажимите на IOS. Потом вам необходимо будет выбрать папку, где у
вас будут собираться все айос- приложения(Выбрать директорию проектов).
Потом нажимаете на Создать проект xcode и у вас готово приложение для айфонов и
айпадов.
Нет художников
По этому поводу писал один человек https://vk.com/renpy?w=wall-
7553243_24357%2Fall и я с ним согласен.
530
2018 Ren’Py
531
2018 Ren’Py
1) КОСТЫЛЬНЫЙ
2) ИСТИНЫЙ
532
2018 Ren’Py
Это значит, что текстовые кнопки, и остальная информация в виде текста не будет
отображена в автоматическом переводе, а так же изображения.
Текстовые кнопки, текст, и название меток и любая другая текстовая информация пишут
хештег такой _(" ")
https://lemmasoft.renai.us/forums/viewtopic.php?f=51&t=43333
533
2018 Ren’Py
2) ХАЙКЕРСКИЙ СПОСОБ
534
2018 Ren’Py
535
2018 Ren’Py
Подумайте оно вам нужно? Если с целью изучения кода более опытных программистов,
без цели заработка или злого умысла следующий раздел для вас
НАЧАЛО РАБОТЫ
Для начала вам необходимо будет скачать питон 2.7 зайдите на офф
сайт и скачайте 2.7 версию https://www.python.org/downloads/
Установите его в вашем компьюторе, что бы в путях не было русских
символов.
Далее вам понадобится скачать 2 специализированых модуля
UNRPA
536
2018 Ren’Py
UNRPYC
537
2018 Ren’Py
Казалось было все отлично, я все извлек, но при запуске exe файла
выходила ошибка.
Я опять к нему обратился, и тогда вместе помозговав стали смотреть
историю декомпиляции, и увидели что 1 файл не смог
распаковаться и пишет ошибку. Гардарик по быстрому написал
разработчику модуля и тот через 4 дня обновил модуль, и он смог
декомпилировать его без ошибок
И там столько накручено в Myth в качестве защиты, что нельзя
удалять папку python и ехе ибо потом не работал весь проект.
https://www.renpy.org/doc/html/skins.html
Заходим в папку где у вас установлен ренпай, Находим папку launcher и заходим в нее.
Далее копируем папку theme и вставляем ее в папку game что в папке launcher
Запускаем ваш лаунчер и вот у вас такая милая тема. Если хотите свое изображение
вставить то поменяйте изображение theme_background.jpg в папке theme
538
2018 Ren’Py
539
2018 Ren’Py
PS
1. Не забудьте, что при этом у вас НЕ должно быть строки
build.classify('game/**.**', 'archive')
2. Все расширения, что не указаны в build.clasifsy НЕ ВОЙДУТ в
архив
3. Не забудьте прописывать build classify('saves/**.**', None) , так как
там, помимо сейвов, хранятся постоянные переменные..
САЙТЫ
1) https://vk.com/renpy
540
2018 Ren’Py
541
2018 Ren’Py
8) http://dobrochan.com/vn/index.xhtml
Анонимный форум по визуальным новеллам
9) https://translate.google.com/translate?
depth=2&nv=1&rurl=translate.google.com&sl=ja&sp=nmt4&tl=ru&u=https://
www.freem.ne.jp/win/game/16349 - через гугл переводчик
https://www.freem.ne.jp/win/category/4/page-1 - оригинал сайт
Японская версия анивизуала
10) https://itch.io/games/genre-visual-novel
Английская версия анивизуала
11) https://vndb.org/v/all
Википедия по всем новеллам
12) https://vk.com/renpy?w=wall-7553243_5103
интервью с Питоном
13) https://m.habr.com/company/miip/blog/321460/
Игры не всегда должны развлекать
14) https://core-rpg.net/articles/analytics/genre/rpg-codex-state-of-rpg-
writing
В какой глубокой заднице находится повествование современных
ролевых игр и почему
15) https://yadi.sk/i/_aumiray3WMMMk
Пример технического задания для художника по фонам
16) https://yadi.sk/i/BB7KA6ry3UjohK
Корявый пример сценария
17) https://vk.com/cyber_z_craft?w=wall-98171527_25432
Переводчики-аферисты
542
2018 Ren’Py
18) http://app2top.ru/game_development/psihotipy-igrokov-za-chto-igroki-
gotovy-platit-95619.html
Психотипы игроков: за что игроки готовы платить?
19) http://www.gamedis.ru/?p=1919
Основные ошибки на кикстарте
20) https://stopgame.ru/blogs/topic/86850
Почему женщины в России не понимают видеоигр
21) https://vk.com/cyber_z_craft?w=wall-100803289_775
Как работать с художниками
22) https://dtf.ru/18645-virtualnye-otnosheniya-kak-zastavit-igroka-polyubit-
npc
как игрока заставить полюбить нпс
23) https://vk.com/cyber_z_craft?w=wall-76362432_1055
очень полезная книга, обязательно изучите ее
24) https://vk.com/cyber_z_craft?w=away-76362432_1033
Разработка кинетической новеллы
543
2018 Ren’Py
http://adrive.com/ - 50 ГБ бесплатно
http://mediafire.com/ - 10 ГБ бесплатно
http://mimedia.com/ - 10 ГБ бесплатно
http://cubby.com/ - от 5 до 25 ГБ бесплатно
http://asuswebstorage.com/ - 5 ГБ бесплатно
http://wuala.com/ - 5 ГБ бесплатно
http://idrive.com/ - 5 ГБ бесплатно
544
2018 Ren’Py
545