Соглашения
Сквозные правила, действующие везде в SDK. Каждая справочная страница их предполагает.
Без импортов — всё глобально
Вся поверхность SDK (Scene, Sprite, UIScreen, Vec3, fetch, …) внедряется на этапе сборки;
пользовательский код её никогда не импортирует. Единственные import в проекте — это относительные
пути к его собственным файлам (import { hud } from './ui/hud') и к его ассетам (import hero from './hero.png'). Голый импорт пакета — ошибка сборки.
Точка входа: файл без экспортов. В многофайловом проекте он связывает остальные вместе и
запускает приложение (Router.init(home) или scene.open()).
Ассеты: ссылайся на файл проекта через import или встроенный макрос asset('./path') — это
переписывание на этапе компиляции, поэтому путь должен быть строковым литералом. Удалённые
https://… URL — обычные строки.
Время
setLoop(dt => …)срабатывает каждый кадр;dt— это секунды с прошлого кадра (~0.016 при 60 fps). Движение, независимое от кадра, —position += speed * dt.setTimeout/setIntervalпринимают миллисекунды.- Длительности анимаций — миллисекунды:
animate({ duration })и UI.animateTo()/.animateFrom()(duration,delay).
Пространство, единицы, углы
2D (Scene2D) |
3D (Scene) |
UI / экран | |
|---|---|---|---|
| Оси | X вправо, Y вверх | правая система, Y вверх, вперёд = −Z | X вправо, Y вниз |
| Единица | 1 мировая единица = 1 логический px при zoom 1 | ≈ метры | логические px (dp/pt) |
| Углы | rotation в градусах, CCW |
eulerAngles в градусах |
— |
- Аргументы-«сырые углы» — радианы (
Quat.fromAxisAngle,Mat4.rotate*,Vec2.rotate); эйлеровы свойства и фабрики — градусы (node.rotation,Quat.fromEuler).DEG2RAD/RAD2DEG— константы времени компиляции для конвертации. - Экранные координаты (
clientX/clientY,device.width/height) — логические px (как iOS pt / Android dp), никогда не физические пиксели;device.pixelRatio— отношение физических к логическим. - Одна ловушка знака: в 2D-мире Y смотрит вверх, но экранный Y и пространство якоря спрайта смотрят
вниз (
anchor: [0.5, 1]= низ-центр = «ноги»).
Цвета
Везде, где принимается цвет, работает всё это (ColorInput):
hex-строки "#e33", "#e33c", "#ff3333", "#ff3333cc"; упакованный int 0xff3333 (только
24-битный RGB — альфу нельзя передать числом); нормализованные массивы дробных [r, g, b] /
[r, g, b, a] (0..1).
hex — единственная строковая форма. CSS-стиль rgba(...) / именованные цвета не парсятся — они
молча становятся непрозрачным чёрным. (UI-стили — исключение: они идут в UI-движок со своим
парсером — см. Стилизацию UI.)
Семантика значений в математике
Vec2 / Vec3 / Quat / Mat4 — изменяемые структуры с чистыми методами: поля можно
присваивать (v.x = 3), но каждый метод возвращает НОВОЕ значение и никогда не меняет источник. Они
итерируемы и взаимозаменяемы с сырыми кортежами — [0, 1, 0] работает везде, где принимается Vec3.
Геттеры трансформа узла возвращают свежие копии (семантика значений, как в Unity):
node.position.x = 3 // ✗ тихий no-op — меняет отброшенную копию
node.x = 3 // ✓ сеттер одной оси
const p = node.position; p.y += 1; node.position = p // ✓ поменять локальную, присвоить обратноСобытия
- Сцены, узлы,
device,WebSocket, медиаплееры:addEventListener(channel, cb)/removeEventListener(channel, cb). - UI-элементы вместо этого используют чейнящиеся методы
on*(.onClick(cb),.onChange(cb)). - События указателя:
clickсрабатывает на отпускании над целью;touchstartсрабатывает на нажатии, и его объект события можетev.track({...}), чтобы захватить остаток жеста. См. События указателя и жесты.
Цепочки
Конструкторы принимают объект опций; настраивающие сеттеры возвращают this, поэтому сборка читается
одной цепочкой. UI-фабрики чейнят .style() и on*. Возможности узла прикрепляются как аспекты
и тоже чейнятся:
const hero = new Sprite({ texture })
.aspect(SpriteAnimation, { size: [32, 48], fps: 10, clips: { walk: [1, 2, 3] } })
.aspect(Shape2D, { box: [16, 8] })
.aspect(Physics2D, { motion: 'dynamic', fixedRotation: true })
hero.anim.play('walk') // каждый аспект добавляет именованный аксессорСм. Аспекты.
Физика владеет динамическими трансформами
Как только у узла есть dynamic-тело (Physics / Physics2D), шаг физики пишет его трансформ.
Не задавай node.position каждый кадр — управляй телом через velocity / applyImpulse
(кинематические тела: moveTo). Чтение node.position / node.worldPosition всегда корректно;
SDK автоматически пересинхронизируется с нативным слоем.
Гейтинг хоста — возможности, которых может не быть
Некоторые возможности зависят от сборки хоста. При отсутствии они молча делают no-op; проверяй через:
Physics.supported(3D-физика),Physics2D.supported(2D-физика)QRScanner.isSupporteddevice.setPreciseTouch()— no-op там, где у платформы нет понятия объединённого ввода
Жизненный цикл
- Всё запущенное в
onOpenэкрана должно останавливаться вonClose(clearLoop,clearInterval,ws.close()), иначе продолжит работать при навигации. - Объекты, оборачивающие нативные ресурсы, освобождают их явно там, где есть метод:
node.destroy()(2D/3D-узлы),player.dispose()(медиа — бросает при любом использовании после),Texture2D.destroy(),response.dispose()(тела fetch). У 3DTextureосвобождения нет — она живёт до закрытия движка.