1. Виртуальный экран вместо window.innerWidth повсюду
Основная конфигурация экрана находится в game/src/config/game.config.ts:
screen: {
land: { width: 960, height: 540 },
port: { width: 540, height: 960 },
dpr: 'auto',
maxDpr: 2,
render: {
scaleFactor: GameRenderScalePolicy.resolveScaleFactor(),
},
},
Я задаю две базовые виртуальные системы координат:
- горизонтальная ориентация:
960 x 540 - вертикальная ориентация:
540 x 960
Это не означает, что игра всегда имеет именно такой размер. Движок читает реальную область просмотра, определяет ориентацию и вычисляет виртуальный canvas, заполняющий доступное пространство.
Упрощённый код из engine/screen/Scaler.ts:
const isLand = viewport.width >= viewport.height;
const orientation = isLand ? 'land' : 'port';
const virt = isLand ? this.config.land : this.config.port;
const useWidth = fit === 'width' || (fit === 'auto' && isLand);
const useHeight = fit === 'height' || (fit === 'auto' && !isLand);
const canvasWidth = useWidth ? virt.width : Math.round(virt.height * (vw / vh));
const canvasHeight = useHeight ? virt.height : Math.round(virt.width * (vh / vw));
Принцип:
- в горизонтальной ориентации стабильной осью обычно служит ширина;
- в вертикальной — высота;
- другая ось выводится из фактического соотношения сторон;
- игровой код работает в виртуальных координатах;
- canvas визуально заполняет область просмотра.
Это делает вёрстку игры предсказуемой и избавляет кодовую базу от повсеместного использования размеров окна браузера.