LeCodesdocs

Устройство проекта

Проект LeCodes — это обычный TypeScript, но несколько правил отличаются от привычной кодовой базы, и каждая страница этого гайда на них опирается. Пять минут здесь сэкономят путаницу везде дальше.

Всё глобально — никаких импортов

Вся поверхность SDK (Scene, Sprite, UIScreen, Vec3, fetch, …) доступна в каждом файле без единого импорта. Сборка подставляет реализацию того, что ты используешь, и вырезает то, что нет, — поэтому глобалы ничего не стоят.

Единственные допустимые import-инструкции в проекте — относительные пути к его собственным файлам и ассетам:

TypeScript
import { hud } from './ui/hud'      // ✓ твой собственный модуль
import hero from './hero.png'       // ✓ ассет — превращается в URL ресурса в бандле
import _ from 'lodash'              // ✗ ошибка сборки: пакетные импорты запрещены

npm здесь нет намеренно: рантайм на устройстве — не Node и не браузер, а компилятору нужно видеть весь код, чтобы ужать его до килобайтов.

Точка входа

Точка входа — файл без экспортов. Маленький проект — это часто один файл; в многофайловом проекте точка входа связывает остальные модули и запускает приложение: для UI-приложения это Router.init(home) или screen.open(), для игры — scene.open().

Ассеты

На файлы проекта (изображения, модели, звуки, шрифты) ссылаются двумя способами — импортом или инлайн-макросом asset():

TypeScript
import hero from './hero.png'                          // одно и то же, две записи
const tex = await Texture2D.load(asset('./hero.png'))

asset()макрос времени компиляции: бандлер переписывает его в ссылку на ресурс, поэтому путь обязан быть строковым литералом — asset(someVariable) не соберётся. Внешним https://… URL макрос не нужен: передавай их обычными строками.

Время: покадровый цикл и таймеры

TypeScript
setLoop(dt => {           // срабатывает каждый отрисованный кадр
  player.x += 120 * dt    // dt — СЕКУНДЫ с прошлого кадра (~0.016 при 60 fps)
})

setTimeout(() => {}, 500) // таймеры принимают МИЛЛИСЕКУНДЫ, как в вебе

Одно соглашение, которое стоит усвоить сразу: dt в setLoop — это секунды. Умножай движение на него — и приложение будет вести себя одинаково при любой частоте кадров. Таймеры и длительности анимаций (animate, UI .animateTo()) — миллисекунды.

И правило-спутник: цикл работает, пока его не остановили. Всё, что экран запускает в onOpen, он обязан остановить в onClose — см. жизненный цикл.

Что делает компилятор

Когда ты нажимаешь «запустить», компилятор упаковывает проект в один портативный app.js: подставляет SDK, разрешает ассеты, инлайнит векторную математику и агрессивно вырезает лишнее — вплоть до неиспользуемых методов классов. Именно этот бандл исполняет каждая платформа, а отрисовка, вёрстка и физика работают как нативный код движков — никакого WebView. Если интересно, как устроены части, — смотри Архитектуру.

Практическое следствие: приложение весит мегабайты, а не десятки мегабайт, и ведёт себя одинаково в браузерном превью, на iOS, Android, Windows, macOS и Linux.

Где смотреть детали

  • Соглашения — единицы измерения, системы координат, цвета, семантика значений: правила, на которые опирается каждая страница API.
  • Глобалы хостаsetLoop, таймеры, asset(), console.
  • Остальной справочник API — каждый глобал, с сигнатурами и единицами измерения.

Что дальше

Выбери трек в обзоре и начинай собирать.