Тайл 32×16 (DEFAULT_ISO). Тайловые координаты всегда {x, y} (целые), экранные — {x, y} в виртуальных пикселях:
import { isoToScreen, screenToIso, screenToIsoExact, DEFAULT_ISO } from '@rpg/engine';
isoToScreen(tx, ty); // экранные координаты ВЕРХНЕЙ вершины ромба
screenToIso(px, py); // приближённый тайл (floor)
screenToIsoExact(px, py, w, h); // точное попадание в ромб или null (для кликов)
Клик по миру: сначала переведите экранные координаты в мировые (позиция worldRoot учитывает камеру), затем screenToIsoExact:
const worldX = pointer.x - engine.renderer.worldRoot.position.x; const worldY = pointer.y - engine.renderer.worldRoot.position.y; const tile = screenToIsoExact(worldX, worldY, map.width, map.height);
Карта — числа (id тайлов) + таблица id → Texture. Блокирующие id не дают ходить; tall — высокие объекты, рисуются поверх земли по строкам глубины:
import { IsometricTileMap } from '@rpg/engine';
const data: TileMapData = {
width: 28, height: 28,
tiles: [...], // length = width * height
blocked: [TILE_WATER, TILE_TREE],
tall: { [TILE_TREE]: { height: 48, ground: TILE_GRASS } } // высота в px, ground — чем рисовать землю под ним
};
const map = new IsometricTileMap(data, textures, DEFAULT_ISO);
worldRoot.addChild(map.view);
map.isWalkable(x, y); // Grid для A*
map.screenSize; // { width, height } для границ камеры
import { findPath } from '@rpg/engine';
const path = findPath(map, { x: 2, y: 3 }, { x: 10, y: 8 });
// путь без стартового тайла, включая конечный; null — пути нет
Диагонали включаются параметром allowDiagonal = true, но без среза углов: диагональный шаг разрешён, только если оба ортогональных соседа проходимы.
Карты можно хранить файлами: encodeMap упаковывает тайлы в RLE (пары [id, длина]), parseMap валидирует и распаковывает:
import { encodeMap, parseMap } from '@rpg/engine';
const file = encodeMap(data); // { format: 'rpg-map', version: 1, encoding: 'rle', tiles: [[0, 12], [1, 3], ...] }
fs.writeFileSync('meadows.json', JSON.stringify(file));
const data = parseMap(JSON.parse(raw)); // бросает понятную ошибку на битых данных
encoding: 'raw' — плоский массив, если RLE не нужен. Файл читается и правится текстовым редактором.
import { fromTiledIso } from '@rpg/engine';
const data = fromTiledIso(tiledJson, {
layers: ['ground', 'props'], // имена слоёв снизу вверх (по умолчанию все tilelayer)
blocked: [2, 5], // id после смещения на firstgid
tall: { 3: { height: 48 } }
});
Требования к карте в Tiled: ориентация isometric, размер тайла 32×16, tilesets один с известным firstgid. GID из Tiled смещаются на firstgid, чтобы id шли с 0; верхние слои заполняют пустые (0) клетки нижних.