docs: what the Ren'Py player does like Ren'Py (layers, rollback, text tags, preferences)
CI / frontend (push) Failing after 19s
CI / backend (push) Failing after 36s

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
mrleo1nidandClaude Sonnet 5.5 committed 2026-10-27 04:39:48 +03:00
1 parent a7034b3563
commit a8902deaf7
2 files changed
+81 -2

No files matched your search

+79
View File
@@ -0,0 +1,79 @@
# Плеер 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` уходят в глубину с
перспективой (CSS `perspective` на слое).
Смена сцены (`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`, ATL `shader`/`mesh`, `u_*`, `gl_*`), поэтому
шейдерные эффекты текста (`{wave}`) и размытие через `blur.rpy` в профилях пропускаются;
частичное `additive` (0 < x < 1).
* Live2D.
* Снимки экрана в слотах сохранения и импорт `.save` Ren'Py.
* Пропуск только прочитанного текста (`preferences.skip_unseen` сохраняется, но не действует).
+2 -2
View File
@@ -43,8 +43,8 @@
## Ограничения
* Не поддерживаются `input`, `imagemap`/`hotspot`, `mousearea`, `drag`/`draggroup`, `side`,
`matrixcolor`, шейдеры и `im.*`; такие экраны блокируют импорт.
* Шейдеры (`shader`, `mesh`, `u_*`) не исполняются; про слои экранов (`onlayer`), камеру,
текстовые теги и остальное, что плеер делает как Ren'Py, — `docs/RENPY_PLAYER.md`.
* Экран перестраивается целиком; положение прокрутки сохраняется, фокус и ввод — нет.
* Позиции без точки (`xpos 1`) читаются как доля, а целые больше 1 — как пиксели.
* Фокус с клавиатуры — только Tab и Enter/Space на кнопках.