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>
This commit is contained in:
1 parent
a7034b3563
commit
a8902deaf7
2 files changed
+81
-2
No files matched your search
@@ -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
@@ -43,8 +43,8 @@
|
|||||||
|
|
||||||
## Ограничения
|
## Ограничения
|
||||||
|
|
||||||
* Не поддерживаются `input`, `imagemap`/`hotspot`, `mousearea`, `drag`/`draggroup`, `side`,
|
* Шейдеры (`shader`, `mesh`, `u_*`) не исполняются; про слои экранов (`onlayer`), камеру,
|
||||||
`matrixcolor`, шейдеры и `im.*`; такие экраны блокируют импорт.
|
текстовые теги и остальное, что плеер делает как Ren'Py, — `docs/RENPY_PLAYER.md`.
|
||||||
* Экран перестраивается целиком; положение прокрутки сохраняется, фокус и ввод — нет.
|
* Экран перестраивается целиком; положение прокрутки сохраняется, фокус и ввод — нет.
|
||||||
* Позиции без точки (`xpos 1`) читаются как доля, а целые больше 1 — как пиксели.
|
* Позиции без точки (`xpos 1`) читаются как доля, а целые больше 1 — как пиксели.
|
||||||
* Фокус с клавиатуры — только Tab и Enter/Space на кнопках.
|
* Фокус с клавиатуры — только Tab и Enter/Space на кнопках.
|
||||||
Reference in new issue
Block a user