О чем этот пример
Начинающие разработчики часто путают объекты `Graphics` и `Rectangle` в Phaser 3, считая их взаимозаменяемыми для рисования простых фигур. Этот пример наглядно показывает ключевую разницу в их поведении при отрисовке, которая может привести к неожиданным артефактам. Понимание этой особенности поможет избежать проблем с графикой и правильно выбирать инструмент для задачи.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Demo extends Phaser.Scene
{
constructor()
{
super();
}
create ()
{
const g = this.add.graphics();
g.fillRect(0, 0, 400, 300);
const g2 = this.add.graphics();
g2.fillRect(400, 0, 400, 300);
this.add.rectangle(400, 300, 64, 64, 0xff0000);
}
}
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 800,
height: 600,
pixelArt: true,
backgroundColor: '#00007d',
scene: Demo
};
const game = new Phaser.Game(config);
Анализ исходного кода
В примере создаётся сцена, где на холст добавляются три графических объекта. Первые два создаются через систему Graphics, а третий – через фабрику геометрических фигур. Ключевая деталь – включён режим pixelArt и задан тёмно-синий фон.
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 800,
height: 600,
pixelArt: true,
backgroundColor: '#00007d',
scene: Demo
};
Проблема: артефакты на стыке Graphics
Два объекта Graphics рисуют прямоугольники, которые соприкасаются по вертикальной линии x=400. Из-за режима pixelArt: true и особенностей рендеринга canvas/WebGL, на границе между ними может появиться видимая щель или артефакт в 1 пиксель.
const g = this.add.graphics();
g.fillRect(0, 0, 400, 300);
const g2 = this.add.graphics();
g2.fillRect(400, 0, 400, 300);
Объекты Graphics рисуют примитивы «как есть», и их границы могут некорректно совмещаться в пиксельной графике, особенно когда координаты целочисленные.
Решение: использование Rectangle
Третий объект создаётся через this.add.rectangle. Это не примитив для рисования, а полноценный игровой объект (Game Object) с текстурами и физическим телом (при необходимости). Его границы обрабатываются иначе, и он не создаёт артефактов на стыках.
this.add.rectangle(400, 300, 64, 64, 0xff0000);
Phaser внутренне оптимизирует рендеринг таких объектов, что делает их предпочтительными для статичной или динамической геометрии в сцене.
Когда использовать Graphics, а когда Rectangle
Выбор зависит от задачи:
* Graphics: Для динамического рисования (карандаш, линии, сложные фигуры), временной графики или кастомных визуальных эффектов, где форма меняется каждый кадр.
* Rectangle (или Circle, Triangle): Для статичных или редко меняющихся фигур в игровом мире. Эти объекты легче, поддерживают взаимодействие (ввод, физику) и не имеют проблем с пиксельными артефактами.
Использование Graphics для сетки из множества статичных квадратов – частая ошибка, ведущая к проблемам с производительностью и отрисовкой.
Что попробовать дальше
Всегда предпочитайте готовые игровые объекты (Rectangle, Circle) для статичной геометрии, а Graphics оставляйте для динамического рисования. Для экспериментов попробуйте
- отключить
pixelArt: trueи увидеть, как пропадает артефакт - создать сетку из
RectangleиGraphicsдля сравнения производительности - добавить физические тела к прямоугольникам и посмотреть, как они взаимодействуют
