Everlasting Summer

Everlasting Summer

26 个评价
Как создать QTE для своего мода?
由 Eternal 制作
Здесь я попробую объяснить, как создавать самое простое QTE в БЛ, а так же параллельно объясню принцип его действия.
   
奖励
收藏
已收藏
取消收藏
Вступление
Всем привет! В этом руководстве я постараюсь рассказать, как создать QTE на renpy для вашего мода на БЛ (Бесконечное Лето). За основу я брал код из другого мода, самостоятельно всё изучил и разобрал, а теперь по предложению из комментариев под моим модом с QTE, я пишу это руковоство. Посмотреть, как примерно будет выглядеть QTE в моде, ты можешь вот тут. Приступим.
Начало
Думаю, как создавать мод, ты можешь посмотреть в других руководствах, но вкратце объясню.






Создаём блок init:, далее с новой строки (всегда в блоках создаём отступ из обязательно четырёх пробелов) и пишем, как на картинке:
  • $ mods["Название лейбла"] = u"Название мода"
Про Название лейбла расскажу чутка позже, а в Названии мода пишете то, как будет называться ваш мод в БЛ.
  • $ config.developer = True
Эта строка не обязательна, но для удобства разработки можно её написать, чтобы мы могли перезагружать БЛ и смотреть изменения в моде, не перезаходя в игру.

Вот мы и создали мод, теперь надо его начинать наполнять.
Первые лейблы
Для того, чтобы добавлять что-то в мод, надо создать блок label, как на картинке:


Пишется оно так:
  • label Название лейбла
На месте Названия лейбла ты, что логично, пишешь название лейбла, а также это название вставляешь в строку $ mod в разделе "Начало" на место Название лейбла.

В самый первый лейбл я предлагаю написать вот такое:



Это надо для того, чтобы мод включался не резко, а плавно через черный экран. Музыку можешь ставить любую, я для примера поставил дефолтную, а после fadein ставишь время включения музыки в секундах, а в последней строке
  • jump Название лейбла 2
вместо Название лейбла ты пишешь название основного лейбла.
Основной лейбл
После создания первого лейбла мы создаём основной лейбл, в котором мы добавим на экран фон, персонажей, текст. Создаётся он так же, как и прошлый. Выглядеть он примерно будет так:






Разберём каждую строку отдельно.
  • $ day_time()
Эта строка включает дневной вид интерфейса, так что используется в зависимости от ситуации (если надо другое время суток, то вместо day пишешь prolog - зимний, sunset - вечерний, night - ночной).
  • $ persistent.sprite_time = 'day'
Эта строка работает так же, как и прошлая, но она меняет освещение спрайта. В зависимости от времени суток спрайт будет разной яркости (если надо другое время суток, то вместо day пишешь prolog - зимний, sunset - вечерний, night - ночной).
  • hide sl with dissolve
Эту строку я писал для очистки экрана от спрайта Слави, но это используется чисто в конце, если ты захочешь создать возвращение к контрольной точке в случае проигрыша. With dissolve, кстати, делает анимацию появления/пропадания плавной, так что мы его будем использовать часто. Вместо sl ты можешь писать название спрайта, который используешь.
  • scene bg ext_houses_day with dissolve
Эта строка добавляет на экран фон, в моём случае это дорожка с домиками днём, вместо ext_houses_day ты можешь написать название своего.
  • show sl normal pioneer far with dissolve
Эта строка добавляет на экран Славю в пионерской форме с обычным настроем далеко, вместо sl normal pioneer far ты опять же можешь писать то, что будешь использовать у себя.
  • alpha 0 align(0.5, 0.1)
  • easein_quad 1 alpha 1 align(0.5, 0.2) zoom 1.1
Эти две строки создают для спрайта анимацию, так что если добавляешь это, то добавь двоеточие к концу строчки добавления спрайта и сделай отступ в 4 пробела. Разберём, что тут написано:
alpha - прозрачность объекта (чем ниже значение, тем прозрачней объект), принимает значения от 0.0 до 1.0
align - положение объекта на экране. В скобках указываем сначала x (от 0.0 до 1.0), а потом y (от 0.0 до 1.0) через запятую.
easein_quad - время действия анимации, значение в секундах.
zoom - приближение/удаление объекта (чем ниже значение, тем дальше объект).
  • sl "Твоя цель - как можно быстрее нажать на нужную клавишу, время будет ограниченно."
Эта строка создаёт реплику персонажа. Сперва мы пишем кодовое имя персонажа, а потом текст в кавычках. Вместо sl ты можешь ставить своего персонажа. Текст тоже можешь менять.
  • pause 1
Эта строка просто создаёт паузу перед следующим действием в коде. Значение указывается в секундах.
  • call qte_sl_start
Эта строка вызывает следующий лейбл, в нашем случае это будет лейбл старта QTE. Вместо qte_sl_start ты можешь написать своё название лейбла старта QTE.
Лейбл старта QTE
Перед началом создания лейбла старта QTE мы сначала создаём в блоке init переменную. Выглядит создание переменной вот так:


  • $ game = -1
Вместо game ты можешь написать любое название, а вместо -1 - любое значение, кроме 0 и 1. Потом поймёшь почему.

Также по желанию можно добавить затемнение экрана по краям. Для этого нужно найти подходящую картинку и добавить её в мод. Делается это так:


Вместо blackqte ты пишешь своё название картинки, а в ковычках указываешь путь до картинки, начиная от папки mods.

Теперь мы готовы к созданию лейбла старта QTE.

Снова создаём блок label со своим названием, всё так же как и в прошлые разы. Выглядеть он будет примерно так:








Снова давай разберём каждую строку отдельно.
  • $ game = -1
Тут мы чистим значение переменной, давая изначальное. Эта строка нужна, если мы добавим возвращение к контрольной точке в случае проигрыша. В ином случае эту строку можно не добавлять. Вместо game ты пишешь название своей переменной, вместо -1 - любое значение, кроме 0 и 1.
  • stop music fadeout 1
В этой строке мы выключаем музыку, после fadeout ставим время выключения музыки в секундах.
  • pause 1
Пауза перед следующим действием. Уже объяснял.
  • play music music_list["doomed_to_be_defeated"] loop fadein 1
Тоже уже объяснял. Но тут мы запускаем более напряжённую музыку для QTE.
  • show sl angry pioneer far with dspr:
  • easein_quad 1 align(0.5, 0.4) rotate -6 zoom 1.3
Тут мы в первой строке меняем спрайт Слави на злой, используя with dspr, вместо dissolve. Это надо, чтобы спрайт заменился быстро, так как dspr быстрее.
Во второй строчке прописываем анимацию для спрайта Слави, в моём случае это +- красивое приближение спрайта к игроку. Тут все слова известны, кроме rotate - это наклон персонажа, значение пишем в градусах (положительное значение - направо, отрицательное - налево).
  • show bg ext_houses_day:
  • easein_quad 1 align(0.5, 0.5) zoom 1.2
Это тоже +- красивое приблежение фона к игроку вместе со спрайтом, чтобы было красивенько.
В первой строке мы обращаемся к нашему фону, так что пишем ранее написанное название.
Во второй строке мы прописываем анимацию, здесь нам всё известно.
  • show blackqte with dissolve
А вот в этой строке мы добавляем эффект затемнения по краям на экран. После show указываем название, которое мы использовали при добавлении этой картинки в мод.
  • pause 1
Снова пауза.
  • call screen qte_sl
А здесь мы вызываем на экран screen.. Скоро мы его создадим. Вместо qte_sl ты напишешь своё название скрина. Начинается само создание QTE.
Скрин QTE
Вот мы и подошли к самому созданию QTE. Для этого мы создаём экран, делается это так же, как и с лейблом, только вместо label, ты пишешь screen. Выглядит это так:

  • screen Название скрина:
Вместо Названия скрина ты пишешь своё название. Логично, да?

Перед заполнением скрина, нам надо добавить картинки кнопок. Понадобится 3 картинки кнопки: просто кнопка, нажатая кнопка и пропущенная кнопка. Добавляем их в мод так же, как делали с затемнением экрана.




Сам скрин QTE выглядит вот так:







Разберём каждую строку отдельно.
  • add "a":
Здесь мы добавили на наш скрин картинку. Тут это происходит немного иначе, чем в лейбле.
Вместо a ты пишешь своё название просто кнопки. Не пропусти двоеточие в конце.
  • at transform:
Эта строка - блок, в котором мы создаём анимацию для добавленной картинки.
  • around(0.5, 0.5) xalign 0.8 yalign 0.2 rotate 0
  • parallel:
  • alpha 0.0
  • easein_quad 0.5 alpha 1.0
  • parallel:
  • ease 0.5 rotate -5 zoom 1.0
  • ease 0.5 rotate 5 zoom 1.05
  • repeat
Это всё анимация. Сложно объяснить, так что лучше просто перепишите таким же образом, как на скриншоте выше. Щас я скажу, какие значения можно менять.
Менять можно значения xalign (положение объекта по x) и yalign (положение объекта по y), они принимают значения от 0.0 до 1.0.
Ещё поменять можно значения rotate и zoom в предпоследней строчке, что они делают, ты знаешь.
  • key "K_a" action [Hide("qte_sl"), Show("qte_sl_end", game = 0), Jump("qte_sl_end_label1")]
Это сложная строчка, постараюсь объяснить. key позволяет нам совершить какое-либо действие на нажатие какой-либо клавиши.
В кусочке K_a ты можешь вместо a написать любую клавишу.
action - это действия, которые мы совершим при нажатии на заданную нами клавишу.
В кусочке Hide("qte_sl") вместо qte_sl ты пишешь название своего скрина старта QTE.
В кусочке Show("qte_sl_end", game = 0) вместо qte_sl_end ты напишешь своё название скрина финала QTE (мы его создадим позже). А вместо game ты пишешь название своей созданной ранее переменной (тут мы даём ей значение 0).
В кусочке Jump("qte_sl_end_label1") вместо qte_sl_end_label1 ты напишешь своё название лейбла победы QTE (мы его тоже создадим позже).
  • timer 3 action [Hide("qte_sl"), Show("qte_sl_end", game = 1), Jump("qte_sl_end_label2")]
Это тоже довольно-таки сложная строчка, но она похожа на прошлую.
timer позволяет нам выполнить какое-то действия спустя некоторое время.
После timer ты указываешь, сколько времени будет у игрока на нажатие нужной кнопки), время в секундах.
В кусочке Hide("qte_sl") вместо qte_sl ты пишешь название своего скрина старта QTE.
В кусочке Show("qte_sl_end", game = 1) вместо qte_sl_end ты напишешь своё название скрина финала QTE (мы его создадим позже). А вместо game ты пишешь название своей созданной ранее переменной (тут мы даём ей значение 1).
В кусочке Jump("qte_sl_end_label2") вместо qte_sl_end_label2 ты напишешь своё название лейбла проигрыша QTE (мы его тоже создадим позже).
Скрин финала QTE
Теперь пришла очередь написать скрин финала QTE, в котором мы сделаем проверку, нажал игрок нужную кнопку или нет. Создаётся этот скрин точно так же, как и прошлый.

Но сперва добавим пару звуков. Нам понадобится звук верно нажатой кнопки и звук неверно нажатой кнопки соответвенно. Добавляются звуки так:


  • $ Название = "путь"
Вместо Названия ты пишешь.. название своего звука, а вместо Пути.. путь до звука.

Время создания и наполнение скрина. Выглядеть он будет так:













Разберём снова строки отдельно.
  • if game == 0:
Тут мы устраиваем проверку, что если наша переменная (в моём случае game) равна 0 (обязательно ставим 2 знака равно), то выполнится код ниже. Вместо game пишешь название своей ранее созданной переменной.
  • add "a_pressed":
Тут мы выводим на экран нашу ранее добавленную картинку нажатой кнопки. Вместо a_pressed ты пишешь своё название.
  • at transform:
  • around(0.5, 0.5) alpha 1.0 xalign 0.8 yalign 0.2 rotate 0
  • easein_quad 0.5 alpha 0.0
  • parallel:
  • ease 0.5 rotate -5 zoom 1.0
  • ease 0.5 rotate 5 zoom 1.05
  • repeat
Это всё анимация кнопки, здесь в значениях xalign, yalign, rotate и zoom ты пишешь те значения, которые писал в анимации кнопки в экране QTE.
  • timer 0.5 action [Play("sound", complete_qte), Hide("qte_sl_end")]
Эта строка похожая на строку из скрина QTE.
Что делает timer, я уже объяснял, но на этот раз желательно оставить ему значение 0.5.
В кусочке Play("sound", complete_qte) вместо complete_qte ты пишешь название своего звука правильно нажатой кнопки.
В кусочке Hide("qte_sl_end") вместо qte_sl_end ты пишешь название своего скрина финала QTE.
  • else:
Эта строка выполнит код ниже при условии, если наша переменная имеет любое значение, кроме 0. В нашем случае это будет проигрыш.
  • add "a_losed":
Тут мы добавляем на экран картинку, всё точно так же, как и ранее, только картинка уже кнопки пропущенной.
  • at transform:
  • around(0.5, 0.5) alpha 1.0 xalign 0.8 yalign 0.2 rotate 0
  • easein_quad 0.5 alpha 0.0
  • parallel:
  • ease 0.5 rotate -5 zoom 1.0
  • ease 0.5 rotate 5 zoom 1.05
  • repeat
Эта анимация кнопки. Её ты пишешь точно такой же, как и анимацию кнопки правильной.
  • timer 1 action [Play("sound", lose_qte), Hide("qte_sl_end")]
Эта строка точно такая же, как и прошлый timer, точно значение ему мы ставим 1, а вместо lose_qte ты пишешь добавленный ранее звук проигрыша.

Вот и готов наш скрин финала QTE. Остаётся добавить пару лейблов, для концовочки и возможность вернутся к контрольной точке.
Последние лейблы
Ну вот мы близимся к концу. Надо создать будет нам два лейбла. Как это делается мы знаем. Сначала я создам лейбл победы в QTE. Его мы называем так, как назвали в скрине QTE. Выглядеть он будет так:









И вновь разбираем строки отдельно..
  • pause 1
  • stop music fadeout 1
  • pause 1
  • play music music_list["a_promise_from_distant_days"] loop fadein 1
Пауза, остановка нашей напряжённой музыки (значение после fadeout можно менять), ещё одна пауза и запуск уже обычной музыки (значение после fadein можно менять).
  • hide blackqte with dissolve
Тут мы прячем с экрана затемнение по краям, вместо blackqte пишешь название своей картинки.
  • show bg ext_houses_day:
  • pause 0.5
  • easein_quad 1 align(0.5, 0.5) zoom 1
Тут мы обращаемся к нашему заднему фону и делаем ему анимацию... Тут тебе всё известно, можешь менять значения на своё усмотрение.
  • show sl sad pioneer far with dspr:
  • pause 0.5
  • easein_quad 1 align(0.5, 0.4) rotate 0 zoom 1.1
То же самое, что и с фоном. Мы обращаемся к нашему спрайту (его можно поменять в этот момент) и делаем ему анимацию. Тут тебе всё известно, можешь менять значения на своё усмотрение.
  • pause 2
  • sl "Молодец!"
Пауза и небольшой текст, указываешь своё короткое имя персонажа и текст.
  • jump my_qte
Перекидываем нашего игрока в начало мода, чтобы всё началось с нуля :D Ну либо если это QTE вставлено в мод, то пишем вместо my_qte название своего следующего лейбла с продолжением мода..

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










Он идентичен с лейблом победы, за исключением последних строк. Разберём их.
  • sl "Ты проиграл."
  • pause 1
Немного отличающийся текст, а так же пауза, которой ранее не было.
  • call qte_sl_shans_label
Эта строчка вызывает лейбл контрольной точки, его мы создадим с следующем разделе. Вместо qte_sl_shans_label укажешь название лейбла контрольной точки.
Лейбл контрольной точки
Мы ещё ближе к концовке. Создаём лейбл так же, как и всегда. Название его мы пишем такое, какое указали в лейбле проигрыша. Вообще, тут вы делаете сами, как пожелаете, но я покажу максимально сырую свою версию. Выглядеть у меня он будет так:







Как обычно, разбираем строчки.
  • show bg black with dissolve
  • show sl sad pioneer far:
  • ease 0.5 align(0.8, 0.4)
Показываем черный фон, после обращаемся к нашему спрайту и прописываем ему анимацию. Всё что надо ты меняешь под себя.
  • pause 1
  • call screen qte_sl_shans
Пауза и вызов скрина контрольной точки. Вместо qte_sl_shans ты напишешь название своего скрина контрольной точки. Вот и всё.
Скрин контрольной точки
Вот и финишная прямая. Как создавать скрин ты знаешь, так что не останавливаюсь. Названием скрина ты пишешь то, что писал в лейбле контрольной точки.

Но сперва надо добавить немного картинок.. В моём случае это картинка текста и кнопка согласия перехода к началу мода в двух вариациях: с наводкой и без. Примеры:


















Добавляем картинки как и всегда:




  • image qe = "mods/bib/materials/textkontr.png"
  • image yes_idle = "mods/bib/materials/shans/yes_idle.png"
  • image yes_hover = "mods/bib/materials/shans/yes_hover.png"
Вместо qe пишешь своё название картинки текста и путь.
А вместо yes_idle и yes_hover пишешь свои названия картинки кнопки согласия.

Сам скрин выглядеть будет примерно так:










Это самый банальный способ, можно было придумать что-то и получше..
Разбираем каждую строку.
  • add "qe":
  • at transform:
  • alpha 0
  • ease 0.5 alpha 1
Это добавление картинки текста с небольшой анимацией, можешь менять значения на своё усмотрение.
  • imagebutton:
Вот эта строка создаёт кнопку с картинкой, тут ничего не меняется.
  • idle "yes_idle"
  • hover "yes_hover"
А вот эти две строки уже добавляют саму картинку на кнопку.
Вместо yes_idle ты пишешь название картинки кнопки не наведённой, а вместо yes_hover название кнопки наведённой.
Важно, что idle это именно не наведённая кнопка, а hover - наведённая.
  • at transform:
  • xalign 0.1 yalign 0.5 alpha 0
  • ease 0.5 alpha 1
Это просто анимация, значения можно менять на своё усмотрение.
  • action [Hide("qte_sl_shans"), Jump("my_qte")]
Эта строчка выполняет определённые действия, если кнопка была нажата.
В кусочке Hide("qte_sl_shans") ты меняешь qte_sl_shans на своё название скрина контрольной точки.
В кусочке Jump("my_qte") ты меняешь my_qte на своё название лейбла, с которого хочешь начать.

Вот и всё. Наше QTE полностью готово.
Заключение
Вот так вот получилось у меня. Это QTE максимально простенькое и банальное, можно создать и лучше в разы, но моей целью было показать принцип действия.

Пишу руководство я впервые, поэтому могло получится как-то сумбурно или что-то не понятно, однако я старался. Приветствую любую обоснованную критику и пожелания, а так же вопросы. Попытаюсь ответить на каждый.

Пока-пока!
23 条留言
kuzm1ch21 2024 年 12 月 8 日 上午 7:33 
Всем КУ! Я Kuzm1ch - юный мододел, пока что я пишу мод про Алису Двачевскую.
Мод готов на 50%, можете накинуть в профиль идеи и предложения, а так же поддержать.
Буду рад любой поддержке и идее!
Спасибо за просмотр.
ElkaVgope FLX 2.0 2024 年 5 月 15 日 上午 4:42 
а есть где то гайд с вскрытием замков а то нигде найти не могу
YuriForcce 2024 年 4 月 16 日 下午 8:30 
Гайд хороший, но QTE в модах - зло. :AngrySword:
4/5 pos only 2024 年 2 月 14 日 下午 12:12 
мне кажется qte можно сделать попроще, но гайд годный. Сасиба, бро <3
Трах Трахыч 2024 年 2 月 14 日 上午 9:34 
я собстна к чему, к тому чтобы не писать кучу if для каждого key, сразу все в одном месте, а так пос остальному все ок, хотя большинство можно и в одном скрине сделать, даже контрольную точку.
Трах Трахыч 2024 年 2 月 14 日 上午 9:30 
даже label не потребуется рекурсионный, просто тупо в цикле выполнится 8 раз скажем, а после цикла уже if ставить
Трах Трахыч 2024 年 2 月 14 日 上午 9:29 
и тут затупил с рекурсией, не поставил ограничение, хотя это все можно и тупо в цикл for засунуть от 0 до n, где последнее будет n-1 по факту
Трах Трахыч 2024 年 2 月 14 日 上午 9:28 
естестна перед вызовом обнулить поинты
Трах Трахыч 2024 年 2 月 14 日 上午 9:27 
условно говоря вот и весь qte примерно щас набросал
Трах Трахыч 2024 年 2 月 14 日 上午 9:26 
в add забыл "[ind]", а перед ним $ ind = im_key[rnd]