• Страница 2 из 6
  • «
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • »
Форум о визуальных новеллах » Записи участника » Ikuku [85]
Результаты поиска

Ikuku

#16 | Тема: Blade Quest [18+]
У Blade Quest скоро небольшой юбилей, в связи с чем мы решили приготовить апдейт с улучшеной графикой, текстом и просто прикольными штуками. Если кто хочет поучаствовать: нарисовать картинку или, почему бы и нет? — озвучить кого-нибудь из персонажей — стучитесь в группу ВК. Там же, по ссылке чуть больше подробностей и анимированный тизер!

Ikuku

#17 | Тема: Помощь по Ren'Py (Вопрос\Ответ)
Увы, не все так просто -_- Тут сразу две проблемы. Одна - поменьше, легко решаемая: экшен 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

Ikuku

#18 | Тема: Помощь по Ren'Py (Вопрос\Ответ)
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 вернет свежескрытый экран на место, и его придется еще раз скрывать кнопкой. Эту проблему надо решать дополнительно, я пока не знаю, как.

Ikuku

#19 | Тема: Помощь по Ren'Py (Вопрос\Ответ)
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

Ikuku

#20 | Тема: Помощь по Ren'Py (Вопрос\Ответ)
Реализовать можно. Детали реализации зависят от постановки задачи. Попробуйте вызывать метку с мыслями не 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 делается по ситуации.

Ikuku

#21 | Тема: Помогите с созданием экрана (screen)
1. Первое, что нужно - это экран, который, во избежание ненужных кликов вне его, будем вызывать командой call. В этот экран мы запихнем все нужные зоны и кнопки.

Объекты - это draggable drag-объекты. Их можно таскать и бросать, но нельзя бросать на них. Неподвижные зоны 1 и 2 - это droppable drag-объекты. На них можно бросать, но их нельзя таскать. За это отвечают свойства draggable и droppable, которые мы установим в False для соответствующих зон.

2. Инфо-зона (№3) будет фреймом с текстом внутри. Нам от нее требуемтся только чтобы она выводила на экран содержимое переменной. Назовем эту переменную current_message, и зададим ей дефолтное значение оператором default.

3. Функции. Для объектов нам нужно два вида функций: срабатывание по клику и срабатывание по перетаскиванию и сбросу. Первая функция устанавливается в свойстве clicked drag-объекта. Вторая - в свойстве dropped.

От функции по клику нам пока требуется исключительно смена сообщения. Т.е. изменение значения переменной current_message в зависимости от кликнутого объекта. Т.е. внутри функции должно быть что-то вроде:

если кликнутый объект == объекту 1:
запихнуть в переменную current_message такой-то текст
иначе если кликнутый объект == объекту 2:
запихнуть в переменную current_message сякой-то текст

И так далее. Current_message нам доступна внутри функции (надо только объявить, что мы обращаемся именно к ней, с помощью оператора global). А что насчет "кликнутый объект"? А текущий кликнутый объект мы, по идее, должны были бы передать в виде параметра в функцию-обработчик клика, но! В свойство clicked мы должны положить такую функцию, которая не принимает параметров (так уж оно устроено). Так как сказать функции о том, на какой именно объект клацнули? Тут два способа. Один - с помощью curried-функций, это долго объяснять, можете сами почитать вот тут: https://lemmasoft.renai.us/forums/viewtopic.php?p=319388#p319388 (это тема!). Второй чуть проще для понимания: мы заводим глобальную переменнию currently_clicked, в которую будем класть идентификатор текущего объекта.

Итак, код (пока в ошметках, потом в конце будет целиком код проекта):
для curried-функции:
Код
def object_clicked(objId):
    global current_message

    if objId == 1:
        current_message = "Вы кликнули на объект %s" % objId
    if objId == 2:
        current_message = "Вы жмякнули на объект %s" % objId
    return None

curriedObjClicked = renpy.curry(object_clicked)

drag:
    drag_name "Айви"
    droppable False
    clicked curriedObjClicked(1)


Для комбо с SetVariable:
Код
def object_clicked():
    global current_message, objId

    if objId == 1:
        current_message = "Вы кликнули на объект %s" % objId
    if objId == 2:
        current_message = "Вы жмякнули на объект %s" % objId
    return None

drag:
    drag_name "Зак"
    droppable False
    clicked [ SetVariable("objId", 2), object_clicked ]

Во втором случае список функций/экшенов в свойстве clicked берется в квадратные скобки, а функция object_clicked там же вызывается без круглых скобок (это важно).

4. С кликом разобрались. Что с перетаскиванием и сбросом? Тут все проще, потому что функция внутри свойства dragged получает два параметра: объект, который бросили, и объект, в который бросили. То есть просто пишем функцию (код ниже).

Комментарии по коду:
drags[0].drag_name переводится как "возьми значение атрибута drag_name первого объекта в списке перетаскиваемых объектов" (он у нас единственный, мы таскаем объекты по одному). drags - это массив объектов, drags[0] берет из него первый элемент (нумерация списков/массивов идет с нуля)
drop.drag_name перевдится как "возьми значение атрибута drag_name объекта, на который уронили тягаемый объект". поскольку наша дроп-зона по сути своей - тоже draggable-объект, только с иными свойствами, его имя хранится в том же атрибуте.

Внутри if'ов можно задавать значения переменным по своему усмотрению и в зависимости от нужд: вычитать очки из общего числа очков маны, менять сообщения и менять значения других переменных, которые будут управлять отображением объектов на экране. Обратите внимание на условие вывода на экран объекта "Камень".

5. Кнопка возврата/выхода будет прятать наш экран экшеном Return.

Код тестового проекта:
Код
default current_message = ""
default mana_points = 42
default stones_left = 3

init python:
    def object_dragged(drags, drop):
        global current_message, mana_points, stones_left

        if not drop:
            return

        if drags[0].drag_name == "Атака" and drop.drag_name == "Враг":
            mana_points -= 10
            current_message = "Отличным ударом вы прожгли во враге дыру!"

        if drags[0].drag_name == "Атака" and drop.drag_name == "Герой":
            mana_points -= 10
            current_message = "Какое нелепое самоубийство!"
            # return True # этой командой мы можем закрыть окно и прыгнуть на метку конца игры, например!

        if drags[0].drag_name == "Камень":
            current_message = "Герой бросается камнями."
            stones_left -= 1

        if drags[0].drag_name == "Шутка":
            current_message = "Ого! Какой смешной, оказывается, %s!" % drop.drag_name.lower()

        renpy.restart_interaction()
        
        return None

    def object_clicked(objId):
        global current_message

        if objId == 1:
            current_message = "Вы кликнули на объект %s" % objId

        else:
            current_message = "Вы жмякнули на объект %s" % objId

        renpy.restart_interaction()
        return None

    curriedObjClicked = renpy.curry(object_clicked)

screen objects_screen:
    draggroup:
        xysize(1.0, 1.0)

        # Объект
        drag:
            drag_name "Атака"
            droppable False
            clicked curriedObjClicked(1)
            dragged object_dragged
            xalign .5 yalign .4

            label "Файербол" background "#000"

        # Объект
        if stones_left > 0:
            drag:
                drag_name "Камень"
                droppable False
                clicked curriedObjClicked(3)
                dragged object_dragged
                xalign .5 yalign .5

                label "Камень" background "#000"

        # Объект
        drag:
            drag_name "Шутка"
            droppable False
            clicked curriedObjClicked(2)
            dragged object_dragged
            xalign .5 yalign .3

            label "Шутеечка за триста" background "#000"

        # Зона слева
        drag:
            drag_name "Враг"
            draggable False

            frame:
                xysize(.3, .7)
                background "#000"
                text "Кинуть во врага"

        # Зона справа
        drag:
            drag_name "Герой"
            draggable False
            xalign 1.0
            
            frame:
                xysize(.3, .7)
                background "#000"
                text "Наложить на себя"

    # Третья зона, контейнер для сообщений
    frame:
        xysize(.7, .3)
        xalign .5
        yalign 1.0
        background "#000"

        text current_message xalign .5

    # кнопка выхода
    textbutton "Выход" action Return xalign .1 yalign .9

    # Индикаторы
    vbox:
        xalign .9 yalign .9
        label "Очки маны: %s" % mana_points
        label "Камней в карманах: %s" % stones_left

label start:
    call screen objects_screen

    "Конец!"

Ikuku

#22 | Тема: [Проект] Ищем фоновика на подмогу
Нужен фоновик, который смог бы работать в стиле приложенной картинки. Игра практически готова, для ускорения процесса решили просить помощи у добровольцев, рисовать придется пару интерьеров и пару пейзажей забытого села на краю вселенной (горы, степи, покосившиеся дома, тлен и безысходность). Реализм, наши дни.



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

Связь: сюда в личку или в вк (https://vk.com/b.ikuku, паблик: https://vk.com/beautyikuku )
Прикрепления: 4337614.jpg(222.5 Kb)
Сообщение отредактировал Ikuku - Пятница, 22/Июн/2018, 14:58

Ikuku

#23 | Тема: Базовый календарь,ошибка
И первый вариант, и второй, с распрыжкой, технически рабочие, проблема не в конструкции, а в условии в if:

Код
if day_of_weak == 1 and day_of_weak <=5:

читается как "если Х равен 1 и одновременно с этим Х меньше либо равен 5", т.е. единственное значение переменной, которое удовлетворяет такому условию - это 1. В первом куске кода оно не выполняется никогда, т.к. переменную вы до вхождения в него не объявили, и значения у нее нет, во втором, с распрыжкой, выполняется только раз, потому что переменная была объявлена ($day_of_weak = 1). Если исправить на:
Код
if day_of_weak >= 1 and day_of_weak <=5:

- все заработает. Аналогично со вторым условием:
Код
if day_of_weak >=6 and day_of_weak <=7:

Можно свернуть их в if/else, но нужно ли это, зависит от конкретной задачи, пока что такой код будет просто циклить нас в метке days, пока дней не станет 8 а потом выпадать на следующую по тексту в файле метку:
Код
label days:
    if day_of_weak >= 1 and day_of_weak <=5:
        "working"

        $day_of_weak +=1
        jump days

    elif day_of_weak >=6 and day_of_weak <=7:
        "Yeeah"

        $day_of_weak +=1
        jump days

Ikuku

#24 | Тема: Помощь по Ren'Py (Вопрос\Ответ)
Задача сводится к следующему:
1. Создать динамичесое изображение (дисплейабл), который будем использовать вместо статического.
2. Создать набор кнопок, которые управляют его состоянием.

1. Везде, где использовался статический фон (по умолчанию "gui/nvl.png", скорее всего будет в файле screens.rpy), вставляем: DynamicDisplayable(set_nvl_bg). Строчка в итоге будет выглядеть как-то так: background DynamicDisplayable(set_nvl_bg)

DynamicDisplayable - это такая штука, которая получает в качестве параметра функцию, а возвращает дисплейабл (картинку) каждые X секунд, и, по умолчанию - с каждым взаимодействием (кликом мыши).

Заводим вспомогательную переменную, в которой будет храниться текущее значение прозрачности:
Код
default nvl_opacity = 1.0


Описываем функцию set_nvl_bg, которая будет управлять прозрачностью:
Код
init python:
    def set_nvl_bg(st, at):
        return Transform("gui/nvl.png", alpha = nvl_opacity), None


st, at - обязательные параметры для любой функции-параметра DynamicDisplayable, нам они в нашем случае не нужны, просто упоминаем и забываем. Transform() - функция, которая принимает картинку/дисплейабл, набор параметров, и изменяет ее согласно этим параметрам. Аналогично ATL-языку. Нам нужен параметр alpha, его значение берем из переменной nvl_opacity. None означает, что DynamicDisplayable следует обновлять только по кликам мыши/взаимодействиям, а не раз в N секунд.

2. Создаем набор кнопок, которые будут управлять фоном. Для примера - в отдельном экране, потом этот блок нужно будет перенести в экран Preferences и настроить по вкусу. Три кнопки с экшенами, которые меняют прозрачность до предустановленных значений + шкала, которая позволяет настраивать прозрачность свободно.

Код
screen nvl_bg_controls():
    zorder 1000

    vbox:
        xsize 200
        spacing 15
  
  textbutton "100%" action SetVariable("nvl_opacity", 1.0)
        textbutton "50%" action SetVariable("nvl_opacity", 0.5)
        textbutton "25%" action SetVariable("nvl_opacity", 0.25)
        
        bar value (nvl_opacity * 100) range 100 changed alpha_adjust

init python:
    def alpha_adjust(x):
        global nvl_opacity
        
        nvl_opacity = x / 100.0
        renpy.restart_interaction()


Код тестового проекта, собранный и готовый к испытаниям (не забудьте поменять статичный фон на DD, п.1):
Код
define nvltest = Character(None, kind = nvl)

screen nvl_bg_controls():
    zorder 1000

    vbox:
        xsize 200
        spacing 15
        
        textbutton "100%" action SetVariable("nvl_opacity", 1.0)
        textbutton "50%" action SetVariable("nvl_opacity", 0.5)
        textbutton "25%" action SetVariable("nvl_opacity", 0.25)
        
        bar value (nvl_opacity * 100) range 100 changed alpha_adjust

default nvl_opacity = 1.0

init python:
    def set_nvl_bg(st, at):
        return Transform("gui/nvl.png", alpha = nvl_opacity), None

    def alpha_adjust(x):
        global nvl_opacity
        
        # делим на сто, т.к. шкала (bar) работает с величинами от 0 до 100, а значение прозрачности - с 0 до 1.0
        nvl_opacity = x / 100.0
        
        # это чтоб фон перерисовывался в реальном времени
        renpy.restart_interaction()

label start:
    show screen nvl_bg_controls

    nvltest "test"
    nvltest "test2"
    nvltest "test3"

Ikuku

#25 | Тема: Помощь по Ren'Py (Вопрос\Ответ)
dmit, Задача именно в том, чтобы получить в экране меню через caption отдельно то, что лежит в persistent'e и отдельно "Какой-то текст"? Если да, то есть вариант отбивать все, что в persistent, каким-нибудь специальным символом, который точно не будет нигде больше фигурировать, а потом внутри экрана разбивать строку на список, и вынимать нужный кусок списка. Что-то вроде:
Код
menu:
    "[persistent.data[0]]=Какой-то текст":
  pass

    "Другой пункт меню, в котором только текст без переменных":
  pass

(т.е. "=" будет отделять текст кнопки от искомой буквы). И дальше в самом экране:
Код
vbox:
    for i in items:
     python:
      # разбиваем строчку на массив, разделитель - "="
      parts = i.caption.split("=")

      # если "=" в строке не было, то сплит() вернет одноэлементный массив, такие нас не интересуют
      if len(parts) > 1:
       some_text = parts[0] # искомый текст из persistent-переменной, выведенный в пункт меню
      else:
       some_text = ""

        textbutton i.caption action i.action # кнопка меню как есть
        textbutton parts[-1] action i.action # текст без persistent-куска, первый элемент списка parts, начиная с конца. Работает для всех пунктов меню: и тех, в которых была переменная, и тех, в которых не было.
        if some_text:
         textbutton some_text action i.action # только persistent-кусок, если есть

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

Ikuku

#26 | Тема: Воспроизведение фрагмента видео
Joe, а проверьте кодеки и формат видео? Или сразу попробуйте конвертнуть его в, например вебм и затестите на этой вебмке, потому что так-то код у вас рабочий. Если что, при конвертации с vorbis/vp8 точно должно пойти.

Ikuku

#27 | Тема: Помощь по Ren'Py (Вопрос\Ответ)
dmit, Внезапно, оказалось, что я и не в курсе, что в i.caption передается неформатированная строка, вместе с тегами и квадратными скобками, my bad) Но теперь вроде понятно. Вы пытались вытащить по срезу нулевой символ, а поскольку в i.caption лежит весь технический мусор, нулевым символом оказывалась квадратная скобка. Есть решение! Брать нулевой символ не от i.caption, а от renpy.substitute(i.caption). Собственно, renpy.substitute() проводит все форматирование, которое происходит "под капотом" при выводе экрана, и возвращает уже отформатированную строку текста, в том виде, в котором она видна на кнопке. Ну, то есть, код будет выглядеть примерно:
Код
text renpy.substitute(i.caption)[0]

Вроде бы так)

Ikuku

#28 | Тема: Exception при вызове функции из screens.rpy
android, вызывайте Func на месте экшена без скобок:
Код
textbutton "Кнопка" action Func

Смысл в том, что когда мы подставляем в экшен функцию со скобками, мы ее выполняем, и происходит это в любой момент выполнения screen-экрана (перерисовка, взаимодействия, для пользователя незаметно), т.е. по нажатию на кнопку ренпай пытается выполнить не функцию, а результат уже случившегося выполнения функции. Без скобок это имя, т.е. мы говорим "в качестве экшена используй функцию по имени Func".

Но это работает только если ваша функция не принимает параметров, или все параметры необязательные. Функции с параметрами превращать в экшены нужно либо через curried-функции, либо с помощью встроенного экшена Function:
Код
textbutton "Кнопка" Function(Func, <аргументы Func через запятую>)

Ikuku

#29 | Тема: Помощь по Ren'Py (Вопрос\Ответ)
Nevilla, официальная документация (только та, что вот тут: https://www.renpy.org/doc/html/) - очень годное место, чтобы научиться основам, особенно если умеете в английский. Дальше основ нужно уже брать конкретную задачу и рассматривать ее отдельно, много вопросов решаются на лемме, вконтаче есть русскоязычный паблик.
Конкретно гайды по работе с переменными есть и тут, на анивизе, в блоге в разделе Ren'py.

Насчет вашего вопроса: речь идет о Red Embrace: Hollywood? Если да, то там довольно несложная система, судя по коду демоверсии. Если его вскрыть, то выясняется, что:

1. Пол закладывается при создании персонажа в переменную mc_gender (файл mc_customize.rpy, функция pronoun_change_<next/prev>, используется на 324-5 строках в экране выбора пола).

2. После создания персонажа происходит прыжок на метку post_create (common_intro.rpy), самая первая строка этой метки - вызов функции gender_set. Сама функция лежит в codestuff.rpy, 192 строка. В ней, в зависимости от выбранного пола, заполняются все обращения и гендерно-зависимые штуки - это большой ряд отдельных переменных. Сами переменные описываются в codestuff.rpy, 58 строка.

3. Дальше в диалоговых репликах эти переменные просто вставляются в текст в квадратных скобках: 
Код
u "Dead, you mean? Yes, [brother], I am dead. In any other sense, though, I'd be mighty doubtful."


Т.е. при переводе можно будет использовать уже имеющиеся переменные, а если в каких-то местах будет их не хватать, то можно будет завести свои. Объявить их в блоке объявления гендерно-зависимых штук, инициализировать внутри функции gender_set, и использовать в скриптах точно так же, как и все прочие.

Код
if gen == "male": 
   ....
   globals()["verb_e"] = ""

elif gen == "female": 
   ....
   globals()["verb_e"] = "а"

...
"Я заметил[verb_e], что кто-то следит за мной."


Тут могут возникнуть сложности с "they", в русском все-таки нет настолько агендерной формы. Возможно, придется извращаться и избегать форм глаголов в переводе в принципе, или махнуть рукой и тупо вырезать "they" как класс, оставив "he/she".

(А глобально вопрос с переводом гендерно-зависимого текста решается в зависимости от того, что там накодил автор, конечно.)

Ikuku

#30 | Тема: Помощь по Ren'Py (Вопрос\Ответ)
KripWorland,
> В блоке, иницализированным как код python, все отрабатывает, а вот если в коде renpy, то матерится при запуске.

А почему блок python: не подходит? Его же можно и внутри скрипта использовать, не только "init python:". Так-то ренпи не понимает питоновские команды (не только for, но и операцию присвоения тоже), внутри скрипта их надо как-то экранировать (либо долларами построчно, либо в блок python)

Код
"Какой-то диалог."

python:
....for <что-то>

"Еще диалог"

init и python - это два разных указателя на дочерний блок, init говорит "выполни этот кусок при запуске программы", а python - "ниже идет блок питоновского кода". Если их собрать вместе, то получится "выполни этот питоновский код при инициализации", но никто не мешает использовать по отдельности.
Форум о визуальных новеллах » Записи участника » Ikuku [85]
  • Страница 2 из 6
  • «
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • »
Поиск: