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

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


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

Ikuku
Дата: Суббота, 05 Августа 2017, 16:50 | Сообщение # 391
Проверенный
Сообщений: 23
Награды: 2
Репутация: 80
Замечания: 0%
Если коротко, то да: любое отдельное изображение можно перекрасить с помощью im.MatrixColor (но только целиком).

Работает он примерно следующим образом: берет каждый пиксель изображения, и вместо текущего цвета/прозрачности ставит новый, в соответствии со вторым полученным параметром (matrix). Второй параметр может быть либо матрицей/кортежем (это для тех, кому не хватает дефолтных возможностей и кто хочет сделать все руками), либо объектом типа im.matrix (собственно, набор готовых "матриц", каждая из которых заранее сконструирована, чтобы десатурировать, менять цвет, и т.д.)

Если у нас второй параметр - матрица (физически записанная, как список из 20-25 чисел), то измененные цвета каждого пикселя считаются по формуле из документации (переменные от a до t берутся из списка, R, G, B и A - из параметров пикселей оригинальной картинки). Если второй параметр - один из готовых матричных объектов, то о формулах волноваться не надо.

Матричные объекты можно перемножать. Пример из документации: im.matrix.desaturate() * im.matrix.tint(0.9, 0.9, 1.0) читается как "сначала обесцветь, потом покрась (синим, т.к. в tint передан кортеж, обозначающий оттенок синего)"

Список встроенных матричных объектов (МО) (вкратце, из документации):

im.matrix.brightness(b) - МО для изменения яркости. Параметр b принимает значения от -1 до 1, чем меньше, тем темнее.

im.matrix.colorize(black_color, white_color) - МО для покраски "темных" и "светлых" пикселей. "Темные" красятся цветом black_color, светлые, соответственно, white_color. NB: не чисто черные и белые, а именно темные и светлые.

im.matrix.contrast© - МО для изменения контраста. Параметр c должен быть больше нуля, от 0 до 1.0 - понижение контраста картинки, больше 1.0 - увеличение.

im.matrix.desaturate() - МО для обесцвечивания. Краткая запись для im.matrix.saturation(0).

im.matrix.hue(h) - МО для изменения цветности. H - градус смещения цвета по цветовому кругу (круг). Т.е. если изначально цвет пикселя был желтый, и h = 45, то новый цвет станет темно-оранжевым.

im.matrix.identity() - МО для того, чтобы ничего с картинкой не делать. ¯\_(ツ)_/¯

im.matrix.invert() - МО для инвертирования цветовых каналов. "Негатив".

im.matrix.opacity(o) - МО для изменения альфа-канала (прозрачности). Параметр o принимает значения от 0 до 1.0, чем меньше, тем картинка прозрачнее.

im.matrix.saturation(level, desat = (0.2126, 0.7152, 0.0722)) - МО для изменения насыщенности. Параметр level (от 0 (черно-белый) до 1.0 (без изменений)) отвечает за цветность, параметр desat (в скобках приведены дефолтные значения) дополнительно корректирует RGB-уровни картинки для обесцвеченного изображения.

im.matrix.tint(r, g, b) - МО для изменения значений цветовых каналов. Параметры принимают значения от 0 до 1.0, измененный цвет считается в виде доли от оригинала. Т.е., скажем, если значение красного было 70 (из 255 возможных), а в r мы передали .1, новый красный будет равен 7.

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

Код
image bg test = "image.jpg"
image bg test0 = im.MatrixColor("image.jpg", [.5, .5, .5, .5, 0, .2, .2, .2, .2, 0, .3, .3, .3, .3, 0, .1, .1, .1, .1, 0])
image bg test1 = im.MatrixColor("image.jpg", im.matrix.colorize((255, 0, 0), "#00f"))
image bg test2 = im.MatrixColor("image.jpg", im.matrix.hue(45))
image bg test31 = im.MatrixColor("image.jpg", im.matrix.saturation(.5))
image bg test32 = im.MatrixColor("image.jpg", im.matrix.saturation(.5, desat=(0.1, 0.1, 0.722)))
image bg test4 = im.MatrixColor("image.jpg", im.matrix.tint(0.4, 0.4, 1.0))
    
label start:
    show bg test
    "Оригинальное изображение."
    
    show bg test0
    "Случайное изменение цветов с помощью матрицы в параметрах. \n\n \[.5, .5, .5, .5, 0,\n.2, .2, .2, .2, 0,\n.3, .3, .3, .3, 0,\n.1, .1, .1, .1, 0\]"
    
    show bg test1
    "Светлые цвета будут синими, темные - красными. Синий передан строкой (hex-код цвета), красный - кортежем. \n\n im.matrix.colorize((255,0,0), \"#00f\")"
    
    show bg test2
    "Цветность. Поворот цветового круга - 45 градусов. \n\n im.matrix.hue(45)"
    
    show bg test31
    "Обесцвечивание, desat задан по умолчанию. \n\n im.matrix.saturation(.5)"
        
    show bg test32
    "Обесцвечивание, desat задан вручную, со смещением в синюю сторону. \n\n im.matrix.saturation(.5, desat=(0.1, 0.1, 0.7))"
    
    show bg test4
    "Изменение оттенка: красный и зеленый каналы - в .4 от оригинального, синий - без изменений. \n\n im.matrix.tint(0.4, 0.4, 1.0)"


Плюс, изображение, которое возвращает im.MatrixColor(...), можно использовать как любую другую displayable, например, в операторе add в кастомном экране: add im.MatrixColor("image.jpg", im.matrix.hue(45))

P.S. с частично прозрачными png тоже работает.

mrWebster
Дата: Суббота, 05 Августа 2017, 17:05 | Сообщение # 392
Друг сайта
Сообщений: 208
Награды: 0
Репутация: 32
Замечания: 20%
Ikuku, спасибо! До последнего не хотел, чтобы для этого была необходимость в объявлении новых объектов. Но, видимо, придется... Удачи с Вашим проектом.

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

Ikuku
Дата: Суббота, 05 Августа 2017, 17:24 | Сообщение # 393
Проверенный
Сообщений: 23
Награды: 2
Репутация: 80
Замечания: 0%
mrWebster, для того, чтобы выводить дисплэйаблы без объявления, есть хитрое ключевое слово expression. Вроде такого:
Код
show expression im.MatrixColor("lorraine.jpg", im.matrix.hue(45))

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

И спасибо, взаимно :)

Larsy
Дата: Четверг, 24 Августа 2017, 13:11 | Сообщение # 394
Пользователь
Сообщений: 2
Награды: 0
Репутация: 0
Замечания: 0%
Прошу прощения за беспокойство, и, возможно, глупый вопрос.
При старте игры хочу сделать что-то типа вступления. Текст - без объявления
характера. Просто текст от автора. Картинка в качестве фона для окна диалога.
К примеру - какое-то изображение с названием "dialog_window_01.png".
Такое расположение нужно только для предисловия.
Вот макет желаемого результата:
Прикрепления: 2452335.jpg(162.5 Kb)


Сообщение отредактировал Larsy - Четверг, 24 Августа 2017, 13:12

dmit
Дата: Четверг, 24 Августа 2017, 15:53 | Сообщение # 395
Проверенный
Сообщений: 118
Награды: 0
Репутация: 17
Замечания: 0%
Можно использовать отдельный экран:
Код
screen view_txt:
    frame:
        yfill True
        xpos 0.5
        background "dialog_window_01.png"
        add Text("Text Text\ntext text")
label start:
    show screen view_txt
    pause(5.0)
    hide screen view_txt

первое что пришло на ум, а вообще-то можно различными способами ))


планета FOREVER!!!

total
Дата: Четверг, 24 Августа 2017, 17:19 | Сообщение # 396
Разработчик
Сообщений: 102
Награды: 2
Репутация: 24
Замечания: 0%
так это ж NVL обычный... объявить персонаж, настроить отступ и фон и всё

Сопредельные Острова

Larsy
Дата: Четверг, 24 Августа 2017, 22:59 | Сообщение # 397
Пользователь
Сообщений: 2
Награды: 0
Репутация: 0
Замечания: 0%
Спасибо за ответы. Оба варианта работают. )
Неделю, как только начал изучать Ren'Py, и туплю еще, даже когда что-то делаю по готовому уроку.

Runf
Дата: Понедельник, 04 Сентября 2017, 03:50 | Сообщение # 398
Проверенный
Сообщений: 27
Награды: 0
Репутация: 0
Замечания: 0%
Нужно сделать инвентарь и возможность перемещения по локациям. Проблема в следующем, идут постоянные диалоги и просто невозможно мышью никуда кликнуть. $renpy.pause() убирает диалоговое окно, но после нажатия мыши сразу идет либо следующая фраза, либо выкидывает в главное меню. Что делать?

Runf
Дата: Понедельник, 04 Сентября 2017, 06:13 | Сообщение # 399
Проверенный
Сообщений: 27
Награды: 0
Репутация: 0
Замечания: 0%
Ага, про перемещения разобрался здесь http://anivisual.net/blog/2014-09-27-62
Но если поставить textbutton, то она отображается поверх фона, но нажать на нее невозможно, пока идет диалог, а в конце диалога выкидывает в главное меню. Что делать?

mrWebster
Дата: Понедельник, 04 Сентября 2017, 08:12 | Сообщение # 400
Друг сайта
Сообщений: 208
Награды: 0
Репутация: 32
Замечания: 20%
Runf, если тебе нужно, чтобы при отсутствии вывода текста, сохранялся текстбокс, то используй следующую команду:
Код
window show

Вообще, window имеет три положения. Если текстбокс скрывается сам, то он в положении auto.
Касательно меню: я так понял, ты делаешь его не через классическую команду, да? Ну, если тебе так хочется проблем (шучу), то попробуй сделать его через экраны. dmit выше скидывал пример объявления экрана. Воспользуйся его примером как основой, а потом, в процессе игры, сделай необходимый вызов.
В главное меню выкидывает потому, что программа достигает команды return, которая завершает игру. Добавь рандомного текста на вывод.


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

Runf
Дата: Понедельник, 04 Сентября 2017, 09:01 | Сообщение # 401
Проверенный
Сообщений: 27
Награды: 0
Репутация: 0
Замечания: 0%
Ага, понял. Если поставить renpy.imagemap, то можно не только горячие точки установить, но и textbutton к примеру. Просто глупо это делать, если мне нужны только кнопки.
Цитата
window show

Прикольная команда, не знал. но нет, не нужно.
Цитата
Касательно меню: я так понял, ты делаешь его не через классическую команду, да?

Представления не имею, какая классическая, а какая нет.
Я нашел способ, как в примере выше:
screen view_txt:
...
label start:
show screen view_txt
Только внутри кнопки, а не текст. Но только он не работает, в диалоговом окне, печатается текст, а кнопки конечно можно использовать, только желательно бы это делать без диалогового окна. Не посреди беседы, а в конце ее хотелось бы пользоваться меню. imagemap полностью решает проблему, но нет ли какого более простого способа?

Runf
Дата: Понедельник, 04 Сентября 2017, 09:24 | Сообщение # 402
Проверенный
Сообщений: 27
Награды: 0
Репутация: 0
Замечания: 0%
И как можно реализовать, чтобы пауза в репликах диалога была в 2 секунды? В смысле сказал персонаж А фразу, мы нажали пробел и через 2 секунды выводится фраза персонажа Б. Поясню, что спрашиваю не о скорости вывода текста, а о паузах между репликами..

Ikuku
Дата: Понедельник, 04 Сентября 2017, 13:29 | Сообщение # 403
Проверенный
Сообщений: 23
Награды: 2
Репутация: 80
Замечания: 0%
По поводу карты: если нужно настраивать внешний вид, то удобнее всего это сделать через screen language, т.е. как в примере выше - создать экран, накидать на него кнопки для перехода. Но тут есть одна хитрость: чтобы экран "карты" выводился не фоном, параллельно с диалогами, а обязательно требовал реакции пользователя, надо ему в свойствах прописать параметр modal True. Вот так:
Код
screen my_map:
    modal True

    frame:
  # кнопки
  textbutton "Школа" action [ Jump("school_label"), Hide("my_map") ]

label start:
    # диалоги до вывода карты

    show screen my_map

    # что-то еще

Т.е. когда нужный диалог заканчивается, и пришло время перемещаться по локациям, выводим модальный экран-карту, которая будет блокировать любые действия вне себя (в том числе и перемотку диалогов), пока не будет скрыта с экрана. А скрывать ее можно по нажатию кнопок-переходов в локацию (см. пример, в экшене два действия: переход на метку school_label и скрытие экрана).

Если кастомный вид карты не нужен, переход можно организовать с помощью стандартного меню выбора:
Код
label start:
    # диалоги до вывода карты

    menu:
  "Перейти в школу":
   jump school_label
  "Перейти на рынок":
   jump market_label

По второму вопросу... Тут есть несколько путей решения, зависит от того, зачем вообще делать паузу. Если пауза между репликами нужна только в нескольких местах, можно вбить их прямо в диалог:
Код
label start:
    window show # это нужно, чтобы во время пауз окно диалога не исчезало
    "Добро пожаловать в общество задумчивых героев!"
    pause 2.0
    "Мы задумываемся на две секунды перед тем, как ответить."
    pause 2.0
    "Если во время этой паузы юзер кликнет еще раз, то пауза закончится, и начнется следующая строка диалога."

Если пауза нужна везде, вообще везде, перед каждой репликой, можно переопределить оператор say. (Можно было бы попытаться добавить callback-функцию для каждого героя, но я не вижу обходного пути добавления туда команды паузы, чтобы не вылетало с ошибкой interaction inside an interaction.)

Кратко, код для переопределения оператора say:

Это кладете в файл 00saycds.rpy (например, имя не особо важно, важно, чтобы он был в списке выше, чем файлы с диалогами):
Код
python early:
    def parse_pausedsay(lex):
        who = lex.simple_expression()
        what = lex.rest()
        what = what[1:-1]
        return (who, what)

    def execute_pausedsay(o):
        who, what = o
        renpy.pause(2.0)
        renpy.say(eval(who), what)

    def lint_pausedsay(o):
        who, what = o
        try:
            eval(who)
        except:
            renpy.error("Character not defined: %s" % who)

        tte = renpy.check_text_tags(what)
        if tte:
            renpy.error(tte)

    renpy.register_statement("", parse=parse_pausedsay, execute=execute_pausedsay, lint=lint_pausedsay)

Использовать как обычно:
Код
label start:
    window show # это нужно, чтобы во время пауз окно диалога не исчезало
    char "Добро пожаловать в общество задумчивых героев!"
    char "Мы задумываемся на две секунды перед тем, как ответить."
    char "Если во время этой паузы юзер кликнет еще раз, то пауза закончится, и начнется следующая строка диалога."

Runf
Дата: Понедельник, 04 Сентября 2017, 17:39 | Сообщение # 404
Проверенный
Сообщений: 27
Награды: 0
Репутация: 0
Замечания: 0%
Круто, спасибо!
Только после "show screen my_map" пришлось дописать "$renpy.pause()", чтобы скрыть диалоговое окно на следующем лейбле.
А пауза нужна в нескольких местах. К сожалению нажатие пробела полностью сбивает паузу и следующая реплика выводится сразу. Можно этого как-то избежать, чтобы пауза точно была? Оно совершенно не принципиально, если вопрос сложный, но все-таки.


Сообщение отредактировал Runf - Понедельник, 04 Сентября 2017, 18:33

dmit
Дата: Понедельник, 04 Сентября 2017, 19:18 | Сообщение # 405
Проверенный
Сообщений: 118
Награды: 0
Репутация: 17
Замечания: 0%
не прерываемая пауза: $renpy.pause(15.0,hard=True)

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