Вызов call из экрана screen

Чтобы не порушить всю адресацию и прочие неважные нам детальки, в Renpy нельзя из экрана делать call (переход на метку с последующим возвратом). Можно перейти на метку в новом контексте, но тогда Renpy спрячет все экраны screen. Это пример того, как можно организовать call по кнопке и отобразить спрятанные экраны, словно их и не прятали. Но кнопку, по которой мы прыгнули на метку, лучше спрятать. Или заменить кнопкой возвращения назад.



# чтобы вызвать локацию кнопкой на экране screen,
# нужно вызывать в ее в новом контексте.
# то есть открывается как бы другая игра.
# и прячутся все прежние экраны.

# вот только при сохранении игры, запоминается только место,
# откуда был вызван первый call, словно все return уже сработали
# поэтому возможность сохранения лучше отключить
# итого: способ работает только для всяких менюшек,
# но не для ветвления сюжета
init python:
    # стек для хранения состояния экранов до вызова call
    screens = []
    # действие по кнопке ESC
    gamemenu = config.game_menu_action
    # добавить очередной список экранов
    def s_push(item):
        global screens
        screens.append(item)
    # извлечь последний список экранов
    def s_pop():
        global screens
        if len(screens) > 0:
            return screens.pop()
        return []
    # стартовое количество денег для тестирования
    money = 10
    # флаг вызова локации в новом контексте
    is_call = False
    # из экрана нельзя выполнить обычный call label
    # создадим его аналог
    class MyCall(Action):
        def __init__(self, label, *args, **kwargs):
            self.label = label
            self.args = args
            self.kwargs = kwargs
        def __call__(self):
            global screens, is_call
            # отключаем ESC
            config.game_menu_action = NullAction()
            # запоминаем экраны
            s_push(renpy.current_screen().screen_name)
            # включаем флаг вызова нового контекста (чтобы спрятать кнопку)
            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)

# экран из которого можно выполнить call
screen test:
    text _(str(money) + " денег") align(.05, .05)
    # кнопку показываем лишь, если не выполнен call по ее нажатию
    if not is_call:
        # кнопка, которая выполняет аналог call label
        textbutton _("Чит") align(.95, .05) action MyCall("menu1")
    else:
        # вызов call из метки, которая уже вызвана с помощью call
        textbutton _("Хинт") align(.95, .05) action MyCall("hnt")

label start:
    show expression "images/bg.jpg"
    show screen test
    "Вы создали новую игру Ren'Py."
    "Добавьте сюжет, изображения и музыку и отправьте её в мир!"
    return

# другая локация, из которой можно вернуться в то же место игры
# при желании можно передавать параметры при вызове
# тогда, вызывать например так можно: ... action MyCall("menu1", plus=100)
label menu1(plus=10):
    # отобразить все экраны, спрятанные при вызове локации в новом контексте
    $ show_screens()
    # собственно какие-то действия
    $ loop1 = True
    # зацикливаем до нажатия 3-й кнопки
    while loop1:
        menu:
            "+[plus]":
                $ money += plus
            "-[plus]":
                $ money -= plus
            "Вернуться":
                $ loop1 = False
    # возвращаемся туда, откуда пришли, восстанавливая прежнее положение дел
    # вместо return
    $ MyReturn()()
    return

label hnt:
    scene black
    centered "Подсказка: это вложенный вызов call из другого call."
    $ MyReturn()()
    return

Комментарии

  1. А как сделать, чтобы при нажатии подсказки экран выбора скрывался?

    ОтветитьУдалить
    Ответы
    1. наверное, вызывать подсказку по-другому. например, вместо action MyCall("hnt") использовать просто action [renpy.call_in_new_context("hnt")]

      Удалить
  2. Добавил к коду
    init:
    image side golova_orka = "Images/golova_orka.png"
    define m = Character("Орк", color="#000000", image="golova_orka")

    Но появилась проблема. Когда возращаюсь к диалогу, цвет черный как я и хочу, то что это говорит НПС Орк, тоже видно, а вот "говорящая голова" пропадает. При следующей реплике, она конечно опять появляется, но вот при возвращении к диалогу из локации, image="golova_orka" куда-пропадает :(
    Подскажите пожалуйста, что делать?

    ОтветитьУдалить

Отправить комментарий