Пользователи · Новые посты · Правила форума · Поиск по форуму · · · Регистрация
Форум о визуальных новеллах » Для разработчиков » Ren'Py » Помощь по Rep'Py (Вопрос\Ответ)
Помощь по Rep'Py (Вопрос\Ответ)

TERNOX
Дата: Вторник, 30 Сентября 2014, 21:50 | Сообщение # 1
Администратор
Сообщений: 420
Награды: 42
Репутация: 846
Сюда пользователи сайта могут писать вопросы о тех или иных функциях движка Ren'Py, а мы попытаемся на них ответить:)


Я у мамы ямаман.

AngelGrove
Дата: Вторник, 14 Ноября 2017, 14:01 | Сообщение # 451
Проверенный
Сообщений: 10
Награды: 0
Репутация: 0
Замечания: 0%
И вновь я и опять проблема... bad Мне надо сделать так, что бы при нажатии на кнопку (imagebuttom) отображался экран, но полностью скрывался интерфейс и оставался один лишь фон (ибо всплывающий экран на прозрачном фоне).

Попробовал сделать через action [Show ("name",_layer="name"), Hideinterface()] с переносом экрана на отдельный слой - всё получилось, но как закрыть экран и вернуть всё как было до нажатия? cry Пробовал [Hide ("name"), Return()] - не вышло...


Ты будешь моим братиком?

Сообщение отредактировал AngelGrove - Вторник, 14 Ноября 2017, 14:05

mrWebster
Дата: Вторник, 14 Ноября 2017, 16:45 | Сообщение # 452
Друг сайта
Сообщений: 208
Награды: 0
Репутация: 32
Замечания: 20%
AngelGrove, думаю, это можно сделать через скрины. В блогах на этом сайте есть подробный разбор работы с ними.

Добро пожаловать во Мрак!

Ikuku
Дата: Вторник, 14 Ноября 2017, 17:44 | Сообщение # 453
Проверенный
Сообщений: 23
Награды: 2
Репутация: 80
Замечания: 0%
Увы, не все так просто -_- Тут сразу две проблемы. Одна - поменьше, легко решаемая: экшен Hide, очевидно, не умеет в экраны на слоях, отличных от слоя screen. Поэтому надо будет написать свою экшен-функцию, а в ней уже использовать скрытие с указанием слоя: renpy.hide_screen("name", layer = "mylayer") (да-да, без нижнего подчеркивания, в show_screen с ним, в hide - внезапно без него)
Код
python init:
    def MyHidey():
  renpy.hide_screen("name", layer="mylayer")

Вторая проблема в том, что HideInterface, судя по проведенным тестам, по окончанию user interaсtion восстановит не только интерфейс, но и свежескрытый экран тоже. То ли из-за того, что открыли мы экран в одном контексте, скрыли в другом, потом вернулись в прежний и HideInterface вернул все как было, то ли хз. Пока в голову не идет, как обойти эту проблему красиво, в общем, костыльное решение - прятать руками все открытые слои, поочередно, без HideInterface, и потом так же открывать обратно.


Сообщение отредактировал Ikuku - Вторник, 14 Ноября 2017, 17:46

AngelGrove
Дата: Среда, 15 Ноября 2017, 15:38 | Сообщение # 454
Проверенный
Сообщений: 10
Награды: 0
Репутация: 0
Замечания: 0%
mrWebster, Ikuku, это конечно многое не поменяло, но спасибо, будем пробовать. bad

Ты будешь моим братиком?

AngelGrove
Дата: Четверг, 16 Ноября 2017, 16:23 | Сообщение # 455
Проверенный
Сообщений: 10
Награды: 0
Репутация: 0
Замечания: 0%
Попытался я через функцию скрыть слой, но в итоге - ошибка cry





Ты будешь моим братиком?

dmit
Дата: Четверг, 16 Ноября 2017, 18:22 | Сообщение # 456
Проверенный
Сообщений: 118
Награды: 0
Репутация: 17
Замечания: 0%
Вы не правильно вызываете функцию MyHidey. ей нужен хотя бы 1 аргумент.
action [Hide("inventory_screen", MyHidey), Return()]
наверно:
action [MyHidey("inventory_screen", "mylayer"), Return()]


планета FOREVER!!!

Сообщение отредактировал dmit - Четверг, 16 Ноября 2017, 18:30

Ikuku
Дата: Четверг, 16 Ноября 2017, 20:16 | Сообщение # 457
Проверенный
Сообщений: 23
Награды: 2
Репутация: 80
Замечания: 0%
AngelGrove, первое, что вам нужно сделать - внести две правки в экшены кнопок:

Код
textbutton "Инвентарь" action [MyShown, HideInterface()]
textbutton "" action [MyHidey, Return()]


Пояснения по синтаксису:
1. Show("XXX") и Hide("XXX") - это экшены ренпи. Внутри их скобок - параметры, которые они принимают. Если вы пишете кастомную функцию, то не добавляете ее в скобки к Show, а либо заменяете Show на нее, либо просто добавляете в список после запятой. В вашем случае - заменяете.

2. Если Return() и, скажем, HideInterface() мы пишем со скобками, то кастомные экшены - без. Потому что (если вдаваться в детали) на самом деле наш кастомный экшен - не экшен, а функция. В свою очередь, цитируя доки: "экшен (кнопки) может быть функцией, которая не принимает аргументов". Т.е. функция без скобок (=не принимающая аргументы) - экшен.

MyHidey(tag, layer="...") - функция.
MyHidey - функция, которую можно использовать как экшен.

3. Код:
Код
def MyShown():
    renpy.show_screen("inventory_screen", _layer="mylayer")
def MyHidey(tag, layer=None):
    renpy.hide_screen("name", layer="mylayer")

правим на:
Код
def MyShown():
    renpy.show_screen("inventory_screen", _layer="mylayer")
def MyHidey():
    renpy.hide_screen("inventory_screen", layer="mylayer")

В вашем конкретном случае если слой и название экрана вы напрямую указываете внутри функции, то вам не нужно передавать их в нее в виде параметров.

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

AngelGrove
Дата: Пятница, 17 Ноября 2017, 00:13 | Сообщение # 458
Проверенный
Сообщений: 10
Награды: 0
Репутация: 0
Замечания: 0%
Ikuku, спасибо за столь подробный разбор. Всё получилось! (Если не считать проблему с двойным кликом по кнопке). Пытался найти решение проблемы с двойным нажиманием, но так и не нашел (даже на японских сайтах нет ответа) и это печально...

Ты будешь моим братиком?

Ikuku
Дата: Пятница, 17 Ноября 2017, 01:59 | Сообщение # 459
Проверенный
Сообщений: 23
Награды: 2
Репутация: 80
Замечания: 0%
AngelGrove, дальнейшее включает мои догадки о причине проблем, я могу ошибаться.

Первая мысль была: отказаться от HideInterface() и вручную прятать все открытые экраны при показе инвентаря, и показывать их, когда его закрываем. Т.е. примерно так:
Код
def ShowInventory():
    renpy.show_screen("inventory_screen")

    renpy.hide_screen("inventory_button")
    _window_hide() # аналог оператора window hide
    renpy.restart_interaction() # для перерисовки окна игры

def HideInventory():
    renpy.hide_screen("inventory_screen")

    renpy.show_screen("inventory_button")
    _window_show() # аналог оператора window show
    renpy.restart_interaction() # для перерисовки окна игры

Вроде все должно было работать, но всплыли нюансы, касающиеся окна say. Во-первых, в скрипте надо было где-то в самом начале сделать window show, чтобы то, что выше, начало работать, во-вторых, у окна say тоже оказались проблемы с контекстом - вышеописанные функции его (окно) прячут - но почему-то не показывают. причем сама по себе структура (внутри старого скрипта):
Код
"test 123"
$ _window_hide()
pause
$ _window_show()
pause
"test 123"

точно так же как и
Код
"test 123"
$ ShowInventory()
pause
$ HideInventory()
pause
"test 123"

отрабатывает нормально (т.е. когда окно say прячется и вызывается из одного и того же контекста).

На этом этапе задача свелась к тому, чтобы не нарушать контекст, в котором работает инвентарь. И чисто технически можно сделать ужасно хитрый трюк: вынести работу с инвентарем в отдельный лэйбл, который мы будем вызывать по необходимости с помощью call inventory_label, и в нем - в одном и том же контексте! - и прятать/открывать окна.

Не могу сказать, что это прямо чистенько-аккуратно, но это работает. Вот базовый код, дополняйте/режьте/переназывайте переменные под свои нужды как угодно:
Код
init -1 python:
    # Показывает инвентарь
    def ShowInventory():
        renpy.show_screen("inventory_screen")

        renpy.hide_screen("inventory_button")
        _window_hide() # аналог оператора window hide
        renpy.restart_interaction() # для перерисовки окна игры

    # Прячет инвентарь
    def HideInventory():
        renpy.hide_screen("inventory_screen")

        renpy.show_screen("inventory_button")
        _window_show() # аналог оператора window show
        renpy.restart_interaction() # для перерисовки окна игры

    # нет прямого способа экшеном вызвать call на метку, поэтому пилим кастомный
    def CustomCall():
        renpy.call("inventory_label")

screen inventory_button:
    frame:
        xalign .5
        textbutton "Инвентарь" action CustomCall

#Экран инвентаря
screen inventory_screen:
    modal True
    frame:
        xalign .3
        textbutton "Закрыть" action Return()

label start:
    window show # эта строка нужна, чтобы _window_hide и _window_show работали
    show screen inventory_button

    "Testing inventory."
    "Lalala."

    return

label inventory_label:
    "Hi! You're inside the inventory label!"
    $ ShowInventory()
    pause
    $ HideInventory()

    return

Как он работает, пошагово:

1. При нажатии кнопки "Инвентарь" кастомный экшен вызывает служебную метку, создавая для нее новый контекст.
2. В этом контексте прямо из самой метки запускается функция "ShowInventory", которая прячет ненужные окна и показывает нужные. Лэйбл ставится на паузу (ожидаем ввод), чтобы следующая функция не закрыла инвентарь раньше времени. Окно инвентаря модальное, т.е. любые действия вне его блокируются.
3. По нажатию кнопки "закрыть", мы просто имитируем user interaction, "прожимая" паузу внутри лэйбла, скрипт идет на следующий шаг, встречает на нем функцию HideInventory, закрывает ненужные окна и открывает нужные.
4. return возвращает нас из служебной метки ровно на то место в предыдущем контексте, откуда мы ушли в инвентарь (это дает нам воможность открывать инвентарь когда вздумается, не заботясь тем, что мы забудем, куда возвращаться).

(P.S. служебная метка для работы с инвентарем одна-единственная на любое его открытие в любой момент времени, создавать по метке на каждое открытие не нужно.)


Сообщение отредактировал Ikuku - Пятница, 17 Ноября 2017, 02:04

AngelGrove
Дата: Пятница, 17 Ноября 2017, 17:10 | Сообщение # 460
Проверенный
Сообщений: 10
Награды: 0
Репутация: 0
Замечания: 0%
Ikuku, вы мой спаситель. Обязательно попробую! ( ~'ω')~

Ты будешь моим братиком?

AngelGrove
Дата: Четверг, 23 Ноября 2017, 16:57 | Сообщение # 461
Проверенный
Сообщений: 10
Награды: 0
Репутация: 0
Замечания: 0%
И это опять я T.T Сегодня у меня очередной вопрос и даже не знаю, можно ли это реализовать...

Суть в том, что у меня есть некая комната с предметами - на предметы можно нажимать и по идеи, там должно выводиться сообщение, а затем должно возвращаться к тому, что было до нажатия на предмет. Я сделал сообщение через новый лейбл и прикрепил его к предмету, затем в лейбле, из которого я нажал на кнопку, задал условие с Return (мол если сделан прыжок на лейбл с сообщением, то выполнять Return). Всё получается, но после вывода сообщения возвращается к началу лейбла... bad


Ты будешь моим братиком?

dmit
Дата: Четверг, 23 Ноября 2017, 17:54 | Сообщение # 462
Проверенный
Сообщений: 118
Награды: 0
Репутация: 17
Замечания: 0%
Заменить return на jump куда надо?

планета FOREVER!!!

Ikuku
Дата: Четверг, 23 Ноября 2017, 19:24 | Сообщение # 463
Проверенный
Сообщений: 23
Награды: 2
Репутация: 80
Замечания: 0%
Реализовать можно. Детали реализации зависят от постановки задачи. Попробуйте вызывать метку с мыслями не jump'ом, а через call, потому что return с возвращением в случайное место потока работает именно с call.

В качестве примера, мы в свое время делали так:
1. Создается специальный лейбл-карта, в котором будет только "интерактивная" зона, т.е. экран с активными предметами. Закольцовываем этот лейбл любым способом (чтобы все клики не на интерактивные зоны оставляли игрока внутри лэйбла).
Код
label room_interaction:
    show screen room_interaction_screen
    pause

    jump room_interaction # это плохой способ закольцевать лейбл, потому что он добавляет "пустые" шаги в rollback, просто в качестве простой демонстрации

2. На каждую интерактивную зону вешается экшен, который переводит на соответствующий лейбл с мыслями/сообщениями. В конце этого лейбла вешается jump обратно на лейбл-карту.
Код
textbutton "Я - интерактивный объект, жмакни меня!" action Jump("object_1")

label object_1:
    hero "Я даже не хочу говорить, что думаю насчет интерактивного объекта №1!"
    jump room_interaction

3. Вывод дальше по сюжету игры из лейбла room_interaction делается по ситуации.

sa36801
Дата: Пятница, 01 Декабря 2017, 19:53 | Сообщение # 464
Пользователь
Сообщений: 2
Награды: 0
Репутация: 0
Замечания: 0%
Доброго времени суток! Только начал осваивать RENPY, в голове бардак, много вопросов...
Подскажите, как реализовать скроллинг большого изображения, к примеру клавишами или мышью (перетаскивая зажатием кнопки, еще лучше - подводя курсор к краю экрана).

mrWebster
Дата: Пятница, 01 Декабря 2017, 20:24 | Сообщение # 465
Друг сайта
Сообщений: 208
Награды: 0
Репутация: 32
Замечания: 20%
sa36801, в Ренпи есть функция, которая считывает положение мыши, и функции, регистрирующие нажатие клавиш. Попробуйте создать экран, у которого будет своя раскладка клавиш, чтобы он, в нужный момент, двигал изображение. Это общая идея реализации такого функционала, подробнее, увы, пока не могу расписать.

Добро пожаловать во Мрак!
Форум о визуальных новеллах » Для разработчиков » Ren'Py » Помощь по Rep'Py (Вопрос\Ответ)
Поиск: