Некоторые полезные функции (Python) - TrueCat17/Ren-Engine GitHub Wiki
out_msg("from", "error_description")
Для удобства также выводится весь python-стек и идёт запись всего выведенного текста в лог-файл (../var/log.txt
).
Получить кортёж (tuple
) модов в виде ((name1, dir_name1), (name2, dir_name2), ...)
,
где name
- название мода, а dir_name
- название директории, в которой находится мод:
get_mods()
Запуск мода в директории mod_name
:
start_mod("mod_name")
Аналогично переход в основное меню:
start_mod("main_menu")
Немедленный выход из игры (не в меню, а вообще):
exit_from_game()
Ширина окна игры:
get_stage_width()
Высота:
get_stage_height()
Ширина и высота окна:
get_stage_size()
Установить размер окна в 1366x768:
set_stage_size(1366, 768)
Внимание, переменные config.width
и config.height
нужны совсем для других целей, см.
Авто-масштабирование спрайтов.
Развернуть окно на весь экран:
set_fullscreen(True)
Выйти из полноэкранного режима:
set_fullscreen(False)
Загрузить изображение (и обработать im-функциями, если есть) асинхронно, т. е. в отдельном потоке:
load_image("image_path")
Ширина изображения:
get_image_width("image_path")
Высота:
get_image_height("image_path")
Ширина и высота:
get_image_size("image_path")
Получить пиксель в точке (x, y)
изображения "image_path"
(число в формате RGBA, т. е. 0xRRGGBBAA
):
get_image_pixel("image_path", x, y)
Получить координаты мыши:
get_mouse()
Получить координаты мыши относительно кнопки, на которую наведена мышь:
get_local_mouse()
Узнать, нажата ли левая кнопка мыши:
get_mouse_down()
Получить параметр "param"
из файла params.conf
как тип
some_type
(один из str
, float
, int
или bool
):
get_from_hard_config("param", some_type)
Получить максимальное значение фпс (FPS, Frame Per Second, количество кадров в секунду):
get_fps()
Установить максимальное значение фпс в 30
(можно поставить любое число от 1
до 60
включительно):
set_fps(30)
Получить ATL изображения ("список действий"),
зарегистрированного командой image
(см. начало главы Изображения):
get_image("image name")
Например, если изображение было зарегистрировано так:
image bg room = "images/bg/room.jpg"
Или так:
image bg room:
"images/bg/room.jpg"
То get_image("bg room")
вернёт в обоих случаях ["images/bg/room.jpg"]
(конечно, если default_decl_at
пуст, см. статью про ATL)
Узнать, было ли зарегистрировано изображение командой image
:
image_was_registered("bg room")
Показать скрин с именем screen_name
:
show_screen("screen_name") # или renpy.show_screen
Скрыть:
hide_screen("screen_name") # или renpy.hide_screen
Узнать, отображается ли:
has_screen("screen_name") # или renpy.has_screen
Узнать, существует ли метка (label
) some_label:
renpy.has_label("some_label")
Прыгнуть (jump
) на метку some_label:
renpy.jump("some_label")
Вызвать (call
) метку some_label:
renpy.call("some_label")
Последние 2 функции действуют не сразу, а после окончания работы всего питон-кода, в котором они находятся, пример:
python:
print(123)
renpy.jump("some_label") # отмечает, что после этого блока будет выполнен jump на some_label
print(234) # выхода из питон-блока после renpy.[jump/call] нет, поэтому эта строка тоже отработает
Сделать скриншот (по умолчанию вызывается при нажатии на P
(англ.)):
make_screenshot(width = None, height = None)
Где width
и height
- размеры к которым масштабируется скриншот до сохранения (None
- не масштабировать).
Скриншот сохраняется в var/screenshots/
под именем screenshotNNNN.png
.
Разрешить/запретить скрывать курсор при бездействии в текущем моде:
set_can_mouse_hide(False) # False - не скрывать, по умолчанию - True
Используется, например, в главном меню.
Время устанавливается в resources/params.conf
.
Быстро преобразовать float
в int
:
ftoi(3.14)
Работает заметно быстрее int(3.14)
.
Может быть использовано для быстрого отбрасывания дробной частипри отрисовке нескольких тысяч изображений в
ScreenLang.
Получить имя папки текущего мода:
get_current_mod()
Получить время запуска текущего мода (в секундах, как и time.time()
):
get_mod_start_time()
Если вы попробуете засекать время между кадрами вызовами time.time()
примерно таким образом:
prev_my_update_time = time.time()
def my_update():
global prev_my_update_time
dtime = time.time() - prev_my_update_time
prev_my_update_time = time.time()
# using <dtime>
То в случае перевода системных часов или в случае загрузки сохранения вы получите неадеватные результаты,
ведь между кадрами здесь могут пройти минуты или даже месяцы.
Для решения этой проблемы у Ren-Engine есть 2 следующих функции.
Получить время между началом текущего и началом прошлого кадров (в секундах):
dtime = get_last_tick()
Возвращает 0
в init
-блоках или в случае, если это первый кадр после запуска с нуля или загрузки сохранения.
Кроме решения проблемы, эта функция также избавляет нас от кучи рутинной возьни.
Получить сумму вызовов get_last_tick()
для всех предыдущих кадров:
get_game_time()
Также возвращает 0
во время инициализации (выполнение init
-блока).
В некотором роде это аналог для time.time()
без его вышеописанных недостатков.
Обратите внимание, что в пределах одного кадра эти функции всегда будут возвращать одинаковые значения.
Т. е. с их помощью нельзя засечь время выполнения какой-либо функции (к примеру, поиска пути в RPG).
Получить путь до текущего файла:
get_filename(0)
Получить номер текущей строки:
get_numline(0)
Получить путь до текущего файла и номер текущей строки:
get_file_and_line(0)
Число 0
здесь означает именно текущее место (при 1
будет место, откуда вызвана текущая функция, и так далее).
Полученный путь может быть использован, к примеру, для построения пути к изображению,
которое лежит рядом с текущим файлом.
Но вообще эти данные иногда требуются самому движку для более информативного сообщения об ошибке.
build_object('name')
Используется для сборки отдельных специально оформленных сущностей (с двойным нижним подчёркиванием в качестве разделителя) в 1 объект для более удобного доступа.
Пример создания:
def my_map__some_function():
pass
def my_map__music__play(*args):
pass
build_object('my_map')
my_map.my_prop = 'my value'
build_object
в данном случае делает примерно следующее:
my_map = Object()
my_map.some_function = my_map__some_function
my_map.music = Object()
my_map.music.play = my_map__music__play
После этого доступен для использования объект my_map
класса Object
(не путать со стандартным python-классом object
),
который допускает (без выкидывания ошибок) обращение к любым свойствам.
Конечно, это можно делать и вручную, но зачем, если есть специальная функция,
позволяющая делать это одной строчкой кода?
А вот и примеры использования полученного объекта, ничего неожиданного:
my_map.some_function()
my_map.music.play('some_music')
my_map.my_prop += '!'
what = 'prop'
my_map['my_' + what] += '!!' # в квадратных скобках можно "вычислить" название свойства
Ещё может возникнуть вопрос, почему бы не делать это с помощью классов или модулей?
Ну, у модулей в python есть свои недостатки
(например: переусложнённость, циклические зависимости, сложности с сохранением данных).
С классами же есть 2 выхода, и оба весьма корявы:
- Создать экземпляр класса (всего 1, что само по себе нетипично и странно) и
постоянно передавать ненужный
self
в методах, - Добавить
@staticmethod
к каждому методу и дать классу имя с маленькой буквы (+cpickle
отказывается сохранятьstaticmethod
, что совсем катастрофично).
Вот и выходит, что одним из самых разумных методов становится создание таких объектов.
Получить текст (строка в utf-8) из буфера обмена:
s = get_clipboard_text()
Установить текст в буфер обмена:
res = set_clipboard_text("Your Text.")
Функция возвращает True
, если всё прошло удачно и False
в противном случае.
Этот результат можно просто проигнорировать, вовсе не записывая его ни в какую переменную.
Ren-Engine ведёт всю работу в кодировке utf-8
.
В этой же кодировке работает и python3.
Ранее вместо него использовался python2, а там с этим были некоторые проблемы,
для обхода которых было написано несколько функций, о которых и рассказывалось в этом разделе,
а также была дана ссылка на интересную
статью
про устройство utf-8
.
Сейчас же (с переходом на python3) из тех функций сохранилась только 1 (да и та поменяла имя):
-
get_text_width(text, text_size)
- посчитать примерную длинуtext
, отрисованную шрифтом размераtext_size
.
Внимание - функция не учитывает тэги (вроде {b}
- полужирности), разный размер разных символов и
принципиальную неопределяемость размеров разных символов шрифта без самого шрифта.
Рекомендуется на всякий случай к полученному значению добавлять число от 20
до 50
(в зависимости от ситуации).
Кроме того, тут вообще нет (по крайней мере на данный момент) функций для работы с теми символами,
которые складывались бы в один символ, стоя рядом друг с другом.
Поэтому такие вещи рекомендуется не использовать.
Добавить свою функцию, при возвращении которой значения False
сценарий будет стоять на месте:
can_exec_next_check_funcs.append(your_func)
Добавить функцию, которая "перематывает" функцию из предыдущего абзаца:
can_exec_next_skip_funcs.append(your_func)
Не для каждой функции, которая "тормозит" сценарий должна быть аналогичная функция для пропуска.
Например, этим может заниматься связанный по смыслу скрин.
Однако, рекомендуется максимально избегать принципиальной невозможности пропуска.
Для отладочных целей иногда нужно узнавать: какая именно функция останавливает сейчас сценарий?
Эта функция записывается в переменную func_that_stopped_scenario
.
Её можно посмотреть, просто вставив название в консоль движка (Shift+O
).
renpy.seen_image('rn happy')
Возвращает True
если показывалось, иначе - False
.
Изображение rn happy
зарегистрировано командой image
(вроде image rn happy = "images/sprites/rn/happy.png"
).
renpy.seen_audio('sound/music/road.ogg')
renpy.seen_label('label_name')
Где label_name
зарегистрирована так:
label label_name:
# ...
По умолчанию задаётся переменной scale_quality
в файле resources/params.conf
.
Если какой-то мод хочет поменять при своём запуске значение этой переменной, это можно сделать так:
set_scale_quality('1')
Значения (строки):
-
'0'
- оставить видимые пиксели ("лесенку") при масштабировании - используется, например, в RPG; -
'1'
- включить сглаживание ("мыло") - используется, например, в Визуальных Новеллах; -
'2'
- на данный момент то же самое, что и'1'
(поведение библиотеки SDL).
Получить текущее значение можно так:
get_scale_quality()
Узнать версию движка можно функцией get_engine_version()
, которая возвращает строку вроде 0.9.6-2022.10.12
.
Именно эта версия пишется в лог-файле (var/log.txt
).
До знака -
через точку идут номера версий: мажорная, минорная и микро (major, minor, micro).
После - дата последнего изменения в формате год, месяц и число месяца.
Предполагается, что:
- Мажорная версия меняется при добавлении значительной функциональности (вроде поддержки 3D), также именно с этими изменениями будут обычно идти и изменения, ломающие обратную совместимость.
- Минорная версия меняется при изменениях средней важности, обратная совместимость будет сохраняться почти полностью.
- Микро предназначена для мелких и незначительных изменений и исправлений.
- До релиза (версия
1.0
) мажорная версия указывается на месте минорной, а минорная на месте микро; обратная совместимость же может быть сломана при абсолютно любом изменении. - Движок берёт строку версии из файла
Ren-Engine/version
, если его нет или он пуст, то функция возвращает строку"None"
.
make_sure_dir(path)
- возвращает path
, гарантированно оканчивающийся на /
.
get_directory_name(path)
Здесь path
- путь относительно "корневой директории" проекта (содержит resources
и var
).
Возвращает "название" папки (по содержимому файла name
, с учётом языка) или
название игры (window_title
из params.conf
) для "корня" проекта.
Если файл name
отсутствует - просто возвращает path
.
get_root_dir()
- возвращает путь к корню проекта.
Также много интересного можно найти в Ren-Engine/rpy/renpy_api.rpy
.