6.0 KiB
Плеер Ren'Py: что он делает так же, как Ren'Py
Плеер (frontend/src/player/) исполняет сценарий Ren'Py из IR в браузере. Здесь — то, что
повторяет поведение Ren'Py, а не его упрощение. Принцип: если игра приносит свой код (библиотеку
текстовых эффектов, свои displayable, свои настройки), плеер запускает её код, а не заменяет
его собственной копией.
Геометрия трансформаций
rendertransform.ts — порт RenderTransform из renpy/display/accelerator.pyx: обрезка (crop),
size/fit, zoom и отражения, rotate с rotate_pad, 3D-повороты (xrotate, yrotate,
zrotate) вокруг matrixanchor, zpos, zzoom, matrixtransform, якорь по transform_anchor.
Матрицы — Ren'Py (Matrix4: векторы-столбцы, ось z от зрителя); в CSS уходит matrix3d с
отражённым z. xpan/ypan/xtile/ytile — отдельный элемент с повторяющимся фоном.
blend и additive переводятся в mix-blend-mode. Тесты — frontend/tests/rendertransform.test.mjs.
Слои и камера
config.layers задаёт порядок слоёв снизу вверх; слой screens — собственный интерфейс плеера
(текстбокс, меню, экраны), слои до него лежат под интерфейсом, после — над ним. Игра управляет
слоями так же, как в Ren'Py:
show/hide/scene ... onlayer имя,renpy.show/hide/scene(layer=...),renpy.showing,renpy.get_showing_tags,renpy.get_attributesсlayer;show screen/hide screen/call screen ... onlayer имя, свойствоlayerэкрана,renpy.show_screen(_layer=...),renpy.get_screen(layer=...);renpy.add_layer(имя, above=, below=)— порядок сохраняется в сохранении;camera имя at ...иrenpy.show_layer_at(список, layer=)— трансформация всего слоя (анимируемая, с теми же свойствами, что у картинки);perspective True|число|(near, p, far)на слое: картинки соzposуходят в глубину с перспективой (CSSperspectiveна слое).
Смена сцены (with) снимает копию всех слоёв под интерфейсом. preferences.transitions = 0
отключает переходы.
Откат
Плеер хранит снимок состояния на каждом взаимодействии (до 50) и возвращается к предыдущему по
колесу вверх, PageUp и действию Rollback. Журнал очищается при новой игре и загрузке.
Текст
{font},{alpha},{k},{plain},{outlinecolor},{cps}(в том числе{cps=*2}и{/cps}),{a=...}(адреса,show:,hide:,jump:,call_in_new_context:илиconfig.hyperlink_handler),{rb}/{rt}(ruby),{space=N},{vspace=N},{alt},{image=...}.- Свои теги игры (
config.custom_text_tags[...],config.self_closing_custom_text_tags[...]): плеер вызывает функцию игры с(tag, argument, contents), гдеcontents— пары(renpy.TEXT_TEXT | TEXT_TAG, текст); ответ — тот же список, аrenpy.TEXT_DISPLAYABLEвставляет displayable в строку как один символ. Так работают Kinetic Text Tags ({bt},{fi},{sc},{rotat},{chaos},{swap},{move},{omega}),{glitch},{gradient},{explode}и{ruby}в That New Teacher: их библиотеки — обычные скрипты игры. - История, сохранения и перевод видят текст без вызова функций тегов (
parseText(text, false)).
API отрисовки для своих displayable
render.ts: renpy.Displayable, renpy.Render (blit, subpixel_blit, fill, canvas,
subsurface, zoom), renpy.render, renpy.redraw, Text.set_text. Дерево рендера
превращается в DOM и перерисовывается, пока элемент на странице.
Настройки игры
preferences — объект настроек плеера: text_cps, afm_time, afm_enable, fullscreen,
transitions, language, volumes[...], get_volume/set_volume, get_mute/set_mute,
get_all_mixers; default preferences.x = ... добавляет поле. Color(...) — настоящий Color
Ren'Py (interpolate, tint, shade, hexcode, replace_*, rgb/hls/hsv).
renpy.fetch отправляет запрос из браузера (нужен CORS на сервере); без сети игра получает
FetchError, как в Ren'Py.
Шрифты: FontGroup().add(файл, от, до) собирается в одно CSS-семейство с unicode-range.
config.mouse_displayable = MouseDisplayable(...) и config.mouse меняют курсор.
Чего пока нет
- Шейдеры и сетки (
renpy.register_shader, ATLshader/mesh,u_*,gl_*), поэтому шейдерные эффекты текста ({wave}) и размытие черезblur.rpyв профилях пропускаются; частичноеadditive(0 < x < 1). - Live2D.
- Снимки экрана в слотах сохранения и импорт
.saveRen'Py. - Пропуск только прочитанного текста (
preferences.skip_unseenсохраняется, но не действует).