О чем этот пример
При разработке игр часто возникает необходимость точно определить границы игровых объектов для обработки столкновений, позиционирования интерфейса или создания визуальных эффектов. Phaser 3 предоставляет удобные методы для получения крайних точек изображений, даже когда они анимированы или повернуты. В этой статье мы разберем, как использовать эти методы на практике, чтобы создавать более динамичные и отзывчивые игровые сцены.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
graphics;
image1;
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('logo', 'assets/sprites/phaser3-logo.png');
}
create ()
{
this.image1 = this.add.image(400, 300, 'logo');
this.image1.setScale(0.5);
this.tweens.add({
targets: this.image1,
duration: 2000,
scaleX: 2,
scaleY: 4,
ease: 'Sine.easeInOut',
repeat: -1,
yoyo: true
});
this.graphics = this.add.graphics();
}
update ()
{
this.graphics.clear();
const topLeft = this.image1.getTopLeft();
this.graphics.fillStyle(0x00ff00, 1);
this.graphics.fillRect(topLeft.x, topLeft.y, 6, 6);
const topCenter = this.image1.getTopCenter();
this.graphics.fillStyle(0xf0ff0f, 1);
this.graphics.fillRect(topCenter.x, topCenter.y, 6, 6);
const topRight = this.image1.getTopRight();
this.graphics.fillStyle(0xff0000, 1);
this.graphics.fillRect(topRight.x, topRight.y, 6, 6);
const leftCenter = this.image1.getLeftCenter();
this.graphics.fillStyle(0xff00ff, 1);
this.graphics.fillRect(leftCenter.x, leftCenter.y, 6, 6);
const rightCenter = this.image1.getRightCenter();
this.graphics.fillStyle(0x00ff00, 1);
this.graphics.fillRect(rightCenter.x, rightCenter.y, 6, 6);
const bottomLeft = this.image1.getBottomLeft();
this.graphics.fillStyle(0xff00ff, 1);
this.graphics.fillRect(bottomLeft.x, bottomLeft.y, 6, 6);
const bottomCenter = this.image1.getBottomCenter();
this.graphics.fillStyle(0x00fff0, 1);
this.graphics.fillRect(bottomCenter.x, bottomCenter.y, 6, 6);
const bottomRight = this.image1.getBottomRight();
this.graphics.fillStyle(0x0000ff, 1);
this.graphics.fillRect(bottomRight.x, bottomRight.y, 6, 6);
this.image1.rotation += 0.013;
}
}
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 800,
height: 600,
scene: Example
};
const game = new Phaser.Game(config);
Загрузка и создание изображения с анимацией
В начале сцены мы загружаем спрайт логотипа Phaser. В методе create() создаем изображение и сразу применяем к нему начальный масштаб 0.5. Затем добавляем твин, который плавно меняет масштаб изображения по осям X и Y с повтором и эффектом йо-йо. Это создает постоянную анимацию, изменяющую размеры объекта, что важно для демонстрации работы методов получения точек.
this.image1 = this.add.image(400, 300, 'logo');
this.image1.setScale(0.5);
this.tweens.add({
targets: this.image1,
duration: 2000,
scaleX: 2,
scaleY: 4,
ease: 'Sine.easeInOut',
repeat: -1,
yoyo: true
});
Создание графического контекста для отладки
Чтобы визуализировать крайние точки изображения, мы используем графический объект Graphics. Он создается один раз в create() и будет переиспользоваться в каждом кадре для рисования маркеров. В начале метода update() мы вызываем clear(), чтобы стереть маркеры предыдущего кадра, так как изображение движется и поворачивается.
this.graphics = this.add.graphics();
// В update()
this.graphics.clear();
Получение крайних точек изображения
Phaser предоставляет набор методов для получения мировых координат ключевых точек изображения. Каждый метод возвращает объект Phaser.Math.Vector2 с координатами x и y. В примере мы получаем восемь точек: три верхние (левый, центр, правый край), две боковые (центр слева и справа) и три нижние. Эти координаты учитывают текущие трансформации объекта: позицию, масштаб, вращение и происхождение (origin).
const topLeft = this.image1.getTopLeft();
const topCenter = this.image1.getTopCenter();
const topRight = this.image1.getTopRight();
const leftCenter = this.image1.getLeftCenter();
const rightCenter = this.image1.getRightCenter();
const bottomLeft = this.image1.getBottomLeft();
const bottomCenter = this.image1.getBottomCenter();
const bottomRight = this.image1.getBottomRight();
Визуализация точек и вращение изображения
Для каждой полученной точки мы задаем уникальный цвет через fillStyle() и рисуем маленький квадрат размером 6x6 пикселей с помощью fillRect(). Это позволяет наглядно увидеть, как точки перемещаются в пространстве при изменении масштаба и вращении. В конце update() мы добавляем инкремент к свойству rotation изображения, заставляя его непрерывно вращаться. Это демонстрирует, что методы корректно работают даже с вращающимися объектами.
this.graphics.fillStyle(0x00ff00, 1);
this.graphics.fillRect(topLeft.x, topLeft.y, 6, 6);
// ... аналогично для других точек
this.image1.rotation += 0.013;
Практическое применение в играх
Эти методы крайне полезны в реальных проектах. Например, getBottomCenter() можно использовать для точного позиционирования тени под персонажем. getLeftCenter() и getRightCenter() пригодятся для определения точек выхода снарядов из дула оружия, прикрепленного к спрайту. Методы getTopLeft() и getBottomRight() часто используются для расчета ограничивающего прямоугольника (bounding box) при проверке столкновений "по грубой силе" или для отрисовки дебаг-контура. Важно помнить, что координаты возвращаются в мировом пространстве сцены, а не в локальных координатах объекта.
Что попробовать дальше
Использование методов для получения крайних точек изображения в Phaser 3 — это мощный инструмент для точного позиционирования, обработки столкновений и создания визуальных эффектов, которые зависят от границ объекта. Для экспериментов попробуйте изменить происхождение (origin) изображения с помощью setOrigin() и понаблюдайте, как смещаются точки. Или используйте полученные координаты для привязки других игровых объектов, например, частиц, которые будут следовать за углами движущегося спрайта.
