Files
pgames-manager/docs/RENPY_PLAYER.md
T
mrleo1nidandClaude Sonnet 5.5 a8902deaf7
CI / frontend (push) Failing after 19s
CI / backend (push) Failing after 36s
docs: what the Ren'Py player does like Ren'Py (layers, rollback, text tags, preferences)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-27 04:39:48 +03:00

80 lines
6.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Плеер 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` сохраняется, но не действует).