О чем этот пример
При разработке игр часто требуется точное позиционирование объектов, особенно когда речь идет о физике или тайловых картах. Работа с дробными координатами может привести к визуальным артефактам и неожиданному поведению. В этой статье мы разберем, как использовать метод `ceil()` вектора Phaser для округления координат по оси Y в большую сторону, что полезно для выравнивания объектов по сетке или привязки к определенным точкам. Мы рассмотрим практический пример, где наглядно видна разница между исходной дробной координатой и округленной. Этот подход поможет сделать движение объектов более предсказуемым и оптимизировать отрисовку.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
y = 100;
graphics;
text2;
text1;
point2;
point1;
create ()
{
this.graphics = this.add.graphics({ fillStyle: { color: 0x2266aa } });
this.point1 = new Phaser.Math.Vector2(300, 100);
this.point2 = new Phaser.Math.Vector2(500, 100);
this.text1 = this.add.text(100, 50, '');
this.text2 = this.add.text(500, 50, '');
}
update ()
{
this.y += 0.05;
this.point1.y = this.point2.y = this.y;
this.point2.ceil();
this.text1.setText(`y: ${this.point1.y}`);
this.text2.setText(`y: ${this.point2.y}`);
this.graphics.clear();
this.graphics.fillPointShape(this.point1, 20);
this.graphics.fillPointShape(this.point2, 20);
}
}
const config = {
width: 800,
height: 600,
type: Phaser.AUTO,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Подготовка сцены и создание точек
В начале кода определяется класс сцены Example. В нем объявляются переменные для хранения координаты Y, графики, текстовых полей и двух векторных точек.
В методе create() инициализируются основные объекты: графический контекст для отрисовки точек, два вектора с одинаковыми начальными координатами по X (300 и 500) и Y (100), а также два текстовых поля для вывода значений.
this.graphics = this.add.graphics({ fillStyle: { color: 0x2266aa } });
this.point1 = new Phaser.Math.Vector2(300, 100);
this.point2 = new Phaser.Math.Vector2(500, 100);
this.text1 = this.add.text(100, 50, '');
this.text2 = this.add.text(500, 50, '');
Анимация и применение метода ceil()
В методе update(), который вызывается каждый кадр, происходит изменение координаты Y. Она плавно увеличивается, создавая эффект движения точек вниз.
Ключевой момент: обе точки получают одинаковое новое значение Y. Однако для второй точки point2 сразу же вызывается метод ceil(). Этот метод округляет координаты вектора (как X, так и Y) до ближайшего большего целого числа. В данном случае меняется только Y, так как X остается статичным.
this.y += 0.05;
this.point1.y = this.point2.y = this.y;
this.point2.ceil();
Визуализация и отображение данных
Чтобы увидеть разницу между исходной и округленной координатами, их значения выводятся в текстовые поля. Метод setText обновляет содержимое text1 и text2.
Затем графический слой очищается методом clear(), и обе точки отрисовываются заново с помощью fillPointShape(). Размер точки задается радиусом в 20 пикселей. Визуально вы увидите, как левая точка движется плавно, а правая — дискретно, «прыгая» на целые значения Y.
this.text1.setText(`y: ${this.point1.y}`);
this.text2.setText(`y: ${this.point2.y}`);
this.graphics.clear();
this.graphics.fillPointShape(this.point1, 20);
this.graphics.fillPointShape(this.point2, 20);
Конфигурация и запуск игры
Код завершается стандартной для Phaser конфигурацией игры. В объекте config задаются размеры холста, тип рендерера (Phaser.AUTO), ID родительского элемента и основная сцена.
Создание экземпляра Phaser.Game с этой конфигурацией запускает выполнение кода.
const config = {
width: 800,
height: 600,
type: Phaser.AUTO,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Что попробовать дальше
Метод ceil() объекта Phaser.Math.Vector2 — простой, но мощный инструмент для контроля над позиционированием. Он незаменим при создании игр с сеточной логикой, например, пошаговых стратегий или головоломок, где объекты должны «прилипать» к узлам сетки.
Поэкспериментируйте: попробуйте применить floor() для округления в меньшую сторону или round() для математического округления. Также можно модифицировать код, чтобы округлялись обе координаты (X и Y), и понаблюдать за движением точки по диагонали.
