О чем этот пример
При разработке пиксель-арт игр на Phaser разработчики часто сталкиваются с размытием спрайтов и появлением визуальных артефактов при движении камеры или объектов. Эти проблемы возникают из-за субпиксельного рендеринга, когда координаты объектов оказываются дробными. Встроенные настройки движка позволяют легко решить эту задачу, сохраняя чёткость пиксельной графики. В этой статье мы разберём пример использования конфигурационных параметров `roundPixels` и `pixelArt`, которые контролируют выравнивание координат. Вы узнаете, как эти настройки влияют на рендеринг, и как их правильно применять в своих проектах.
Версия 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('pic', 'assets/pics/atari-fujilogo.png');
this.load.image('sprite', 'assets/sprites/mushroom16x16.png');
this.load.image('bik', 'assets/sprites/bikkuriman.png');
}
create ()
{
const a = this.add.image(400, 150, 'bik');
const b = this.add.image(400, 300, 'pic');
const c = this.add.image(100, 300, 'sprite').setScale(10);
const d = this.add.image(700, 300, 'sprite').setScale(10);
let aligned = true;
const left = this.add.text(10, 10, 'Left 0.5px', { font: '16px Courier' });
const right = this.add.text(680, 10, 'Right 0.5px', { font: '16px Courier' });
left.setInteractive();
right.setInteractive();
left.on('pointerdown', () => {
this.cameras.main.zoom += 1;
console.log(this.cameras.main.zoom);
// this.cameras.main.scrollX += 0.5;
// console.log(this.cameras.main.scrollX);
});
right.on('pointerdown', () => {
this.cameras.main.zoom -= 0.5;
console.log(this.cameras.main.zoom);
// this.cameras.main.scrollX -= 0.5;
// console.log(this.cameras.main.scrollX);
});
this.input.on('pointerdown', (pointer) => {
if (pointer.y < 200)
{
return;
}
aligned = !aligned;
a.x += (aligned) ? 0.5 : -0.5;
b.x += (aligned) ? 0.5 : -0.5;
c.x += (aligned) ? 0.5 : -0.5;
d.x += (aligned) ? 0.5 : -0.5;
a.y += (aligned) ? 0.25 : -0.25;
b.y += (aligned) ? 0.25 : -0.25;
c.y += (aligned) ? 0.25 : -0.25;
d.y += (aligned) ? 0.25 : -0.25;
});
}
}
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 800,
height: 600,
roundPixels: true,
pixelArt: true,
backgroundColor: '#000099',
scene: Example
};
const game = new Phaser.Game(config);
Проблема: субпиксельное смещение и размытие
При перемещении игровых объектов на дробные значения (например, на 0.5 пикселя) браузер пытается отрисовать их в промежуточных позициях. Для пиксельной графики это приводит к размытию и нечётким границам, так как пиксели спрайта "растягиваются" между соседними пикселями экрана.
В предоставленном примере эта проблема наглядно демонстрируется. Четыре изображения (bik, pic и два увеличенных sprite) изначально загружаются в сцену. При клике в нижней части холста их координаты `xиy` изменяются на дробные значения 0.5 и 0.25 соответственно.
a.x += (aligned) ? 0.5 : -0.5;
a.y += (aligned) ? 0.25 : -0.25;
Без специальной обработки такие микро-сдвиги сразу же ухудшат визуальное качество пиксель-арта.
Решение: настройка конфигурации игры
Phaser предлагает два ключевых параметра в объекте конфигурации для борьбы с этой проблемой: pixelArt и roundPixels. Их необходимо задать при создании экземпляра Phaser.Game.
Параметр pixelArt: true включает фильтр CSS image-rendering: pixelated, который предотвращает сглаживание растровых изображений при их масштабировании. Это фундаментальная настройка для любого пиксель-арт проекта.
Параметр roundPixels: true заставляет рендерер движка округлять конечные координаты всех отрисовываемых объектов до целых чисел каждый кадр. Это решает проблему субпиксельного смещения.
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
roundPixels: true, // Округляет координаты объектов
pixelArt: true, // Включает резкое масштабирование пиксельной графики
backgroundColor: '#000099',
scene: Example
};
const game = new Phaser.Game(config);
В примере оба параметра активированы, что гарантирует чёткое отображение спрайтов даже при их движении на дробные пиксели.
Интерактивная демонстрация и зум камеры
Пример также включает интерактивные элементы для проверки работы настроек. В верхних углах экрана размещены два текстовых объекта, которые служат кнопками.
const left = this.add.text(10, 10, 'Left 0.5px', { font: '16px Courier' });
const right = this.add.text(680, 10, 'Right 0.5px', { font: '16px Courier' });
При клике на кнопку "Left 0.5px" увеличивается зум камеры (this.cameras.main.zoom), а при клике на "Right 0.5px" — уменьшается. Это позволяет приблизиться к объектам и детально рассмотреть, как ведут себя их пиксели при разных уровнях масштаба, даже с включённым roundPixels.
left.on('pointerdown', () => {
this.cameras.main.zoom += 1;
});
right.on('pointerdown', () => {
this.cameras.main.zoom -= 0.5;
});
Код, изменяющий scrollX камеры на 0.5 пикселя, закомментирован, но его можно активировать, чтобы увидеть, как roundPixels влияет и на рендеринг через камеру.
Логика переключения выравнивания объектов
Основная демонстрация происходит по клику в нижней части холста (pointer.y < 200). Обработчик события pointerdown инвертирует булеву переменную aligned и сдвигает все четыре изображения на фиксированные дробные значения.
this.input.on('pointerdown', (pointer) => {
if (pointer.y < 200) { return; }
aligned = !aligned;
a.x += (aligned) ? 0.5 : -0.5;
// ... аналогично для b, c, d
a.y += (aligned) ? 0.25 : -0.25;
// ...
});
Благодаря roundPixels: true, визуально эти сдвиги на 0.5 пикселя по X и 0.25 по Y не будут заметны — объекты останутся на целых пиксельных координатах. Если отключить эту настройку в конфиге, каждый клик будет приводить к лёгкому "дрожанию" и размытию спрайтов, особенно заметному при большом зуме.
Что попробовать дальше
Использование связки roundPixels: true и pixelArt: true в конфигурации Phaser — это простой и эффективный способ сохранить кристальную чёткость пиксельной графики. Эти настройки берут на себя заботу о выравнивании координат, позволяя разработчику сосредоточиться на геймдизайне и логике.
Для экспериментов попробуйте:
1. Отключить roundPixels и понаблюдать за накоплением дробных координат и появлением артефактов.
2. Раскомментировать код, сдвигающий scrollX камеры, чтобы увидеть, как округление работает и для её позиции.
3. Поиграть с уровнем зума, чтобы понять, при каких масштабах эффект округления наиболее критичен.
