О чем этот пример
Визуальные манипуляции с текстурами — ключ к созданию динамичных и оптимизированных игр. Этот пример демонстрирует продвинутую технику: обрезку (`crop`) одного кадра из текстуры атласа и интерактивное управление этой областью с помощью курсора мыши. Вы научитесь не только изменять отображаемую часть спрайта, но и визуализировать границы обрезки, что незаменимо при отладке или создании таких механик, как просмотр через прицел, открытие дверей или постепенное проявление объектов.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
offset;
graphics;
bob;
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.atlas('atlas', 'assets/atlas/megaset-0.png', 'assets/atlas/megaset-0.json');
}
create ()
{
this.add.image(400, 300, 'atlas', 'phaser2').setAlpha(0.3).setFlipX(true);
this.bob = this.add.image(400, 300, 'atlas', 'phaser2').setFlipX(true);
this.graphics = this.add.graphics();
const cropWidth = 200;
const cropHeight = 100;
this.bob.setCrop(20, 20, cropWidth, cropHeight);
this.offset = this.bob.getTopLeft();
this.input.on('pointermove', pointer =>
{
this.bob.setCrop(
(pointer.x - this.offset.x) - cropWidth / 2,
(pointer.y - this.offset.y) - cropHeight / 2,
cropWidth,
cropHeight
);
});
}
update ()
{
this.graphics.clear();
this.graphics.lineStyle(1, 0x00ff00);
this.graphics.strokeRect(this.offset.x + this.bob._crop.x, this.offset.y + this.bob._crop.y, this.bob._crop.width, this.bob._crop.height);
}
}
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 800,
height: 600,
backgroundColor: '#2d2d88',
scene: Example
};
const game = new Phaser.Game(config);
Инициализация и загрузка атласа
Вся работа начинается с загрузки ресурсов в методе preload. Вместо отдельных изображений загружается текстура атласа и соответствующий JSON-файл с данными о кадрах. Это стандартный и эффективный подход для организации графики в Phaser.
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.atlas('atlas', 'assets/atlas/megaset-0.png', 'assets/atlas/megaset-0.json');
}
Метод setBaseURL задаёт базовый путь для всех последующих загрузок, что упрощает указание относительных путей к файлам.
Создание спрайтов и настройка обрезки
В методе create создаются два спрайта из одного и того же кадра 'phaser2' атласа 'atlas'. Первый служит полупрозрачным фоном (setAlpha(0.3)), чтобы видеть полное изображение. Второй, с именем this.bob, — это основной объект для манипуляций. Оба спрайта зеркально отражены по горизонтали с помощью setFlipX(true).
this.add.image(400, 300, 'atlas', 'phaser2').setAlpha(0.3).setFlipX(true);
this.bob = this.add.image(400, 300, 'atlas', 'phaser2').setFlipX(true);
Затем инициализируется объект Graphics для последующего рисования и определяется исходная область обрезки. Метод setCrop принимает координаты X, Y (относительно верхнего левого угла текстуры спрайта) и размеры области.
const cropWidth = 200;
const cropHeight = 100;
this.bob.setCrop(20, 20, cropWidth, cropHeight);
Важный шаг — получение точки this.offset с помощью getTopLeft(). Это мировые координаты верхнего левого угла спрайта this.bob, необходимые для корректного перевода координат курсора в систему координат текстуры.
Интерактивное управление областью обрезки
Чтобы обрезка реагировала на движение мыши, создаётся обработчик события pointermove. Логика внутри него вычисляет новые координаты обрезки так, чтобы её центр следовал за курсором относительно позиции спрайта.
this.input.on('pointermove', pointer =>
{
this.bob.setCrop(
(pointer.x - this.offset.x) - cropWidth / 2,
(pointer.y - this.offset.y) - cropHeight / 2,
cropWidth,
cropHeight
);
});
Выражение (pointer.x - this.offset.x) переводит мировые координаты курсора в координаты внутри спрайта. Вычитание половины ширины и высоты (cropWidth / 2) центрирует область обрезки под указателем мыши.
Визуализация границ обрезки
Для наглядности границы текущей области обрезки рисуются поверх сцены в методе update. Сначала this.graphics.clear() стирает предыдущий кадр, чтобы линия не "размазывалась". Затем настраивается стиль линии и рисуется прямоугольник.
update ()
{
this.graphics.clear();
this.graphics.lineStyle(1, 0x00ff00);
this.graphics.strokeRect(this.offset.x + this.bob._crop.x, this.offset.y + this.bob._crop.y, this.bob._crop.width, this.bob._crop.height);
}
Ключевой момент — расчёт мировых координат для прямоугольника. Он использует внутренние свойства _crop объекта this.bob, которые хранят текущие параметры обрезки. Эти координаты складываются с this.offset, чтобы преобразовать их из локальных (относительно текстуры спрайта) в мировые координаты сцены, где и должен рисоваться Graphics.
Что попробовать дальше
Вы освоили мощный инструмент для динамического управления отображением текстур. Комбинация setCrop, getTopLeft и Graphics открывает путь к созданию сложных визуальных эффектов. Для экспериментов попробуйте: изменить размер области обрезки в зависимости от скорости движения мыши, анимировать обрезку для эффекта "штор" или "проявления", привязать область обрезки к другому игровому объекту вместо курсора или использовать маску вместе с обрезкой для создания составных эффектов.
