О чем этот пример
При разработке игр часто возникает задача вписать один объект в границы другого. Например, вы хотите, чтобы картинка фона заполнила весь экран, или чтобы иконка предмета идеально поместилась в заданную ячейку инвентаря. Ручной расчёт масштаба и позиции может быть утомительным. Класс `Phaser.Actions` предоставляет для этого удобный статический метод `FitToRegion`. Эта статья покажет, как им пользоваться, и объяснит ключевые параметры для точного контроля над вписыванием.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('bg', 'assets/skies/bigsky.png');
this.load.image('card1', 'assets/pics/card1.png');
this.load.image('card2', 'assets/pics/card2.png');
this.load.image('card3', 'assets/pics/card3.png');
}
create ()
{
const bg = this.add.image(640, 360, 'bg');
// By default, the region is the screen.
Phaser.Actions.FitToRegion(bg);
// Create some non-square cards...
const card1 = this.add.image(320, 360, 'card2');
const card2 = this.add.image(640, 360, 'card1');
const card3 = this.add.image(960, 360, 'card3');
// ... and some square regions.
// We could use anything with x, y, width, height values, e.g. Geom.Rectangle.
const fitRect1 = this.add.rectangle(320, 360, 256, 256).setStrokeStyle(1, 0xffffff, 0.5);
const fitRect2 = this.add.rectangle(640, 360, 256, 256).setStrokeStyle(1, 0xffffff, 0.5);
const fitRect3 = this.add.rectangle(960, 360, 256, 256).setStrokeStyle(1, 0xffffff, 0.5);
// Fit cards to regions.
// Note we override the origin so it will align properly.
Phaser.Actions.FitToRegion(card1, -1, fitRect1, { originX: 0, originY: 0 });
Phaser.Actions.FitToRegion(card2, 0, fitRect2, { originX: 0, originY: 0 });
Phaser.Actions.FitToRegion(card3, 1, fitRect3, { originX: 0, originY: 0 });
this.add.text(320, 640, '-1: Fit inside', { fontFamily: 'sans-serif', fontColor: '#ffffff', fontSize: 24 }).setOrigin(0.5);
this.add.text(640, 640, '0: Fit both', { fontFamily: 'sans-serif', fontColor: '#ffffff', fontSize: 24 }).setOrigin(0.5);
this.add.text(960, 640, '1: Fit outside', { fontFamily: 'sans-serif', fontColor: '#ffffff', fontSize: 24 }).setOrigin(0.5);
// Animate between fitted and original state.
this.tweens.add({
targets: [card1, card2, card3],
scaleX: 1,
scaleY: 1,
duration: 1000,
repeat: -1,
repeatDelay: 1000,
yoyo: true,
ease: 'Quad.inout'
});
}
}
const config = {
type: Phaser.AUTO,
width: 1280,
height: 720,
backgroundColor: '#2f3640',
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Что такое FitToRegion и зачем он нужен
Phaser.Actions.FitToRegion — это статический метод, который масштабирует один или несколько игровых объектов, чтобы они вписались в заданную прямоугольную область (регион). Объект при этом растягивается или сжимается, сохраняя свои пропорции или игнорируя их, в зависимости от выбранного режима.
Основные сценарии использования: * Адаптация фонового изображения под любой размер экрана. * Создание сеток инвентаря или меню, где элементы должны чётко заполнять ячейки. * Динамическая подгонка контента (например, изображений из загрузки) под заранее заданные слоты в интерфейсе.
Базовое использование: фон на весь экран
В примере первым действием фон вписывается в регион по умолчанию — весь экран. Это самый простой вызов метода, который принимает только один аргумент — целевой объект.
// Фон 'bg' будет масштабирован, чтобы целиком заполнить область экрана.
Phaser.Actions.FitToRegion(bg);
Здесь не указан явный регион, поэтому FitToRegion использует в качестве области размеры текущей сцены (или камеры).
Вписывание в произвольные регионы с разными режимами
Мощь метода раскрывается при работе с явно заданными регионами и параметром fitMode. В примере создаются три карточки и три квадратных региона (прямоугольники с контуром).
Регион — это любой объект со свойствами `x,y,width,height. Это может бытьPhaser.Geom.Rectangleили, как в коде, игровой объектRectangle`.
const fitRect1 = this.add.rectangle(320, 360, 256, 256).setStrokeStyle(1, 0xffffff, 0.5);
Ключевой параметр fitMode (второй аргумент) определяет стратегию вписывания:
* -1: Объект масштабируется, чтобы целиком поместиться *внутри* региона, сохраняя пропорции. Могут появиться пустые поля.
* `0`: Объект масштабируется, чтобы *полностью заполнить* регион, сохраняя пропорции. Части объекта могут быть обрезаны.
* `1`: Объект масштабируется, чтобы *полностью покрыть* регион, *игнорируя* пропорции. Регион будет заполнен целиком, но объект может исказиться.
// Карта card1 будет вписана внутрь региона fitRect1 (режим -1).
Phaser.Actions.FitToRegion(card1, -1, fitRect1, { originX: 0, originY: 0 });
Важность точки привязки (origin)
Обратите внимание на последний, необязательный аргумент — объект конфигурации. В примере в нём задаётся { originX: 0, originY: 0 }. Это критически важно для правильного выравнивания.
По умолчанию у изображения точка привязки (origin) находится в центре (0.5, 0.5). Метод FitToRegion масштабирует объект относительно его текущей позиции. Если не изменить origin, после масштабирования центр картинки сместится, и она не будет совпадать с регионом.
Установив origin в (0, 0) (левый верхний угол), мы говорим: "масштабируй объект, но его левый верхний угол должен остаться на месте". Поскольку регионы и карты созданы с одинаковыми координатами, это обеспечивает их точное совмещение после масштабирования.
// Без { originX: 0, originY: 0 } карта масштабировалась бы относительно своего центра и "уплыла" из региона.
Phaser.Actions.FitToRegion(card1, -1, fitRect1, { originX: 0, originY: 0 });
Динамика и анимация
Метод FitToRegion применяет только масштаб (scaleX, scaleY). Это значит, что с изменёнными объектами можно легко работать дальше. В примере используется Tween для анимации, которая плавно возвращает карточки к исходному размеру и обратно к вписанному.
this.tweens.add({
targets: [card1, card2, card3],
scaleX: 1,
scaleY: 1,
duration: 1000,
// ... другие параметры твина
});
Так как FitToRegion лишь меняет свойства scale, его можно вызывать на лету, например, при изменении размера игрового окна, чтобы интерфейс адаптировался.
Что попробовать дальше
Phaser.Actions.FitToRegion — это мощный и лаконичный инструмент для решения задачи "вписать объект в прямоугольник". Понимание параметров fitMode и правильная настройка origin — залог точного результата.
Идеи для экспериментов:
1. Создайте интерфейс настроек, где иконки вписываются в круглые области (используйте регион-квадрат, но задайте объекту круглую маску).
2. Реализуйте адаптивный фон для игры, который пересчитывается при каждом изменении размера окна браузера, снова вызывая FitToRegion для фонового изображения.
3. Используйте метод для нестандартных регионов: попробуйте вписать текст (Phaser.GameObjects.Text) в динамически меняющуюся область диалогового окна.
