Инвентарь с количеством одинаковых предметов (для нового GUI)

 

init python:
    # окно игры в центре экрана
    import os
    os.environ['SDL_VIDEO_CENTERED'] = '1'
    # автоматическое объявление изображений
    config.automatic_images_minimum_components = 1
    config.automatic_images = [' ', '_', '/']
    config.automatic_images_strip = ['images']

    # размеры сетки с инвентарем настраиваются
    inv_cols = 2
    inv_rows = 3

    # размеры иконок в инвентаре
    side = 200

    # ширина и высота инвентаря
    inv_width = inv_cols * side
    inv_height = inv_rows * side - 100

    # чтобы листать вниз при добавлении предметов
    yadjValue = float("inf")
    yadj = ui.adjustment()

    # найти индекс предмета с указанным id
    def inv_geti(id):
        for i in range(len(inventory)):
            if inventory[i][0] == id:
                return i
        return -1

    # изменение количества предметов в ячейке на plus единиц
    # если не было, то будут созданы
    # если количество < 1, то удалены вовсе
    def iplus(id, plus=1, hint=None, about=None):
        global inventory
        # вернется эта переменная
        res = ["", 0, "", ""]
        # ищем индекс предмета с указанным id
        i = inv_geti(id)
        # если такой есть, то меняем количество
        if i >= 0:
            cnt = inventory[i][1]
            if hint is None:
                hint = inventory[i][2]
            if about is None:
                about = inventory[i][3]
            # если plus равен None, то нужно удалить все элементы
            if plus is None:
                cnt = 0
            # иначе добавить нужное количество (можно отрицательное)
            else:
                cnt += plus
                # задаем успешно снятое/добавленное количество предметов
            # предметы количеством < 1 удаляются из инвентаря
            if cnt < 1:
                inventory.pop(i)
            # если количество положительное, то меняем его значение
            else:
                inventory[i] = [id, cnt, hint, about]
        # иначе создаем новый предмет
        else:
            # если пустые поля, то что-то добавляем
            if hint is None:
                hint = _("Хреновина")
            if about is None:
                about = _("Нет описания")
            # создание предмета работает лишь при положительном количестве
            if not plus:
                return res
            elif plus > 0:
                inventory.append([id, plus, hint, about])
                # если добавляем новый предмет в конец списка, то стоит промотать список
                yadj.value = yadjValue
        res = [id, plus, hint, about]
        # изменения на экран
        renpy.restart_interaction()
        # вручную сохраняем измененные данные инвентаря
        # а то renpy сохраняет данные только при смене текста в текстбоксе
        renpy.retain_after_load()

        global inv_last
        # на выходе количество убранных/добавленных или созданных предметов
        inv_last = res
        # возвращаем снятое/добавленное количество предметов
        return res

    # обработчик кликов,
    # чтобы не пихать гору кода в action кнопок
    def iclick(i):
        # например, вызовем окно применения предмета
        renpy.show_screen("scr_use", i)
        renpy.restart_interaction()

    # кнопка применения предмета
    def accept(i):
        # уменьшаем количество предметов на 1
        iplus(inventory[i][0], -1)

    # пролистать в самый верх
    def inv_scroll0():
        yadj.value = 0
        renpy.restart_interaction()

    # превращаем функции в action
    iClick = renpy.curry(iclick)
    Accept = renpy.curry(accept)
    InvScroll0 = renpy.curry(inv_scroll0)

init:
    image inv_empty = Null(side, side)

# необязательное окно применения предмета
screen scr_use(i):
    modal True
    frame:
        background "#100b"
        align(.5, .5)
        xminimum 500
        has vbox:
            xalign .5
        text " "
        add inventory[i][0] xalign .5
        text inventory[i][2] xalign .5 color "#ffb"
        text inventory[i][3] xalign .5 color "#fff"
        text " "
        hbox:
            xminimum 500
            textbutton _("Применить") xalign .5 xminimum 150 action [Hide("scr_use"), Accept(i)]
            textbutton _("Отмена")    xalign .5 xminimum 150 action Hide("scr_use")
        text " "

# сам экран инвентаря
screen scr_inventory:
    on "show" action InvScroll0()
    # zorder 111
    default tt = Tooltip(" ")
    frame:
        xmargin 0 ymargin 0
        xpadding 0 ypadding 0
        align (.95, .05)
        background "#0018" # фон инвентаря
        xmaximum inv_width xminimum inv_width
        vbox:
            text _("Инвентарь") xalign .5 color "#fff" xmaximum inv_width xminimum inv_width
            viewport id "box":
                minimum (inv_width , inv_height)
                maximum (inv_width, inv_height)
                mousewheel True
                draggable True
                pagekeys True
                yadjustment yadj
                # заполняем ячейки
                vbox:
                    for y in range(int((len(inventory) + 1) / (inv_cols))):
                        hbox:
                            for x in range(inv_rows - 1):
                                # индекс ячейки
                                $ i = x + y * inv_cols
                                # если не за грницами списка предметов
                                if i < len(inventory):
                                    button:
                                        xmargin 0 ymargin 0
                                        xpadding 0 ypadding 0
                                        # кликабельны только очертания предмета, не пустота
                                        focus_mask True
                                        # размеры предмета
                                        minimum (side, side)
                                        maximum (side, side)
                                        background inventory[i][0] # картинка предмета
                                        hovered tt.Action(inventory[i][2])
                                        action iClick(i) # действе по клику
                                        # количество
                                        $ cnt = inventory[i][1]
                                        if cnt > 1:
                                            text "x" + str(cnt) align(1.0, 1.0) color "#ffb"
                                else:
                                    # пустые ячейки
                                    add "inv_empty"
            text tt.value xalign .5 color "#ffb" xmaximum inv_width xminimum inv_width

label start:
    # если сначала объявить переменную прямо в скрипте,
    # то renpy будет сам сохранять ее содержимое
    $ inventory = []

    # список для хранения последнего использованного предмета
    $ inv_last = ["", 0, "", ""]

    # заполним инвентарь всеми доступными пузырьками в 1 экземпляре
    $ i = 0
    while i < 9:
        # вторым параметром можно указать стартовое количество хреновин
        # третьим - подсказку, появляющуюся при наведении курсора
        # а можно ничего не указывать, только имя картинки - 1й параметр
        $ i += 1
        $ iplus('pot' + str(i), 1, "Хреновина №" + str(i))

    scene bg
    # покажем экран инвентаря
    show screen scr_inventory
    with dissolve

    "Можно кликнуть по хреновинам в инвентаре."

    # пример изменения инвентаря из скрипта
    # iplus(спрайт, количество, подсказка, описание)
    $ iplus('pot4', 2, "Хреновина №4")

    # смотрим в inv_last, что было добавлено в последний раз
    # [id, количество, название, описание]
    $ id, cnt, hint, about = inv_last
    "{image=[id]} Добавлено ещё [hint], [cnt] штук."
    return

Комментарии