О чем этот пример
При разработке пиксель-арт игр на Phaser вы могли сталкиваться с неприятным визуальным эффектом — дрожанием или размытостью спрайтов при их плавном движении. Это происходит из-за того, что координаты объектов с дробной частью заставляют рендерер отрисовывать изображение между пикселями экрана. В этой статье мы разберем, как свойство `roundPixels` основной камеры позволяет решить эту проблему, обеспечивая четкую, стабильную картинку. Мы изучим практический пример, который наглядно демонстрирует разницу между включенным и выключенным округлением пикселей.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Demo extends Phaser.Scene
{
constructor()
{
super();
}
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('truck', 'assets/sprites/astorm-truck.png');
this.load.image('bik', 'assets/sprites/bikkuriman.png');
this.load.image('squad', 'assets/sprites/bsquadron1.png');
this.load.image('spider', 'assets/pics/spider.png');
this.load.image('case', 'assets/pics/case.jpg');
this.load.script('webfont', 'https://ajax.googleapis.com/ajax/libs/webfont/1.6.26/webfont.js');
}
create ()
{
// this.add.image(400, 300, 'case');
// this.add.image(200.5, 200.8, 'spider');
// this.add.text(200.2, 400.9, 'Round Pixels', { fontFamily: 'Arial', fontSize: 96, color: '#ffffff' });
// this.add.rectangle(500.3, 200.8, 101, 100, 0x00ff00).setOrigin(0);
/*
WebFont.load({
google: {
families: [ 'VT323' ]
},
active: () =>
{
// this.add.text(200, 400, 'The face of the\nmoon was in\nshadow.', { fontFamily: 'VT323', fontSize: 32, color: '#ffffff' });
this.add.text(200, 400, 'phaser with round pixels', { fontFamily: 'VT323', fontSize: 32, color: '#ffffff' });
}
});
*/
this.add.sprite(400, 100, 'truck');
this.add.sprite(400, 200.4, 'truck');
this.add.sprite(400.4, 300, 'truck');
this.add.sprite(400.4, 400.4, 'truck');
this.add.sprite(200, 100, 'bik');
this.add.sprite(200, 200.4, 'bik');
this.add.sprite(200.4, 300, 'bik');
this.add.sprite(200, 400.4, 'bik');
this.add.sprite(600, 80, 'squad').setScale(2);
this.add.sprite(600, 200.4, 'squad').setScale(2);
this.add.sprite(600.4, 320, 'squad').setScale(2);
this.add.sprite(600.4, 440.4, 'squad').setScale(2);
this.add.rectangle(0, 500, 800, 100, 0x00ff00).setOrigin(0).setAlpha(0.2);
this.input.on('pointerdown', pointer => {
if (pointer.y > 500)
{
this.cameras.main.roundPixels = !this.cameras.main.roundPixels;
console.log('camera roundPixels', this.cameras.main.roundPixels);
}
});
}
}
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 800,
height: 600,
pixelArt: true,
backgroundColor: '#00007d',
scene: Demo
};
const game = new Phaser.Game(config);
Проблема: почему пиксели плывут?
В основе проблемы лежит субпиксельный рендеринг. Когда координата спрайта имеет дробную часть (например, X=100.5), движок пытается отрисовать его, сглаживая границы между реальными пикселями экрана. Для фотореалистичной графики это хорошо, но для пиксель-арта — катастрофа.
Четкие пиксельные края размываются, изображение начинает "дрожать" при анимации. В примере специально используются дробные координаты для части спрайтов, чтобы визуализировать этот артефакт.
this.add.sprite(400, 200.4, 'truck');
this.add.sprite(200.4, 300, 'bik');
Решение: включаем roundPixels
Phaser предоставляет простое и эффективное решение — свойство roundPixels у камеры. Когда оно установлено в true, координаты всех отображаемых объектов автоматически округляются до ближайшего целого числа перед отрисовкой на холсте.
В примере это свойство переключается по клику в нижней зеленой области экрана. Состояние свойства логируется в консоль для наглядности.
this.input.on('pointerdown', pointer => {
if (pointer.y > 500) {
this.cameras.main.roundPixels = !this.cameras.main.roundPixels;
console.log('camera roundPixels', this.cameras.main.roundPixels);
}
});
Важное замечание: эта настройка применяется ко всем объектам на сцене, которые видит данная камера.
Важность флага pixelArt
Обратите внимание на конфигурацию игры. В ней явно установлен флаг pixelArt: true. Этот параметр критически важен для корректной работы пиксельной графики в Phaser 3.
Что он делает? 1. Отключает линейную интерполяцию (сглаживание) текстур при их масштабировании. 2. Автоматически включает округление пикселей для всего игрового холста.
const config = {
// ... другие настройки ...
pixelArt: true, // Ключевой параметр для пиксель-арта
backgroundColor: '#00007d',
scene: Demo
};
Использование pixelArt: true в сочетании с roundPixels дает максимально четкий и стабильный результат.
Что происходит на экране?
В примере создается сетка из спрайтов, размещенных с целыми и дробными координатами. При запуске с pixelArt: true вы сразу можете увидеть разницу: спрайты на целых координатах (например, 400, 100) выглядят резко, а те, что имеют дробную часть координаты (400, 200.4), могут выглядеть размыто или сдвинуто, в зависимости от реализации рендерера в браузере.
Зеленая полупрозрачная панель внизу — это интерактивная область для переключения свойства. Кликая по ней, вы увидите, как все спрайты на сцене "привязываются" к целым пикселям, мгновенно становясь четкими, или возвращаются в исходное состояние.
this.add.rectangle(0, 500, 800, 100, 0x00ff00).setOrigin(0).setAlpha(0.2);
Когда использовать, а когда нет?
**Используйте roundPixels (и pixelArt: true), когда:**
* Вы создаете игру в стиле пиксель-арт.
* Ваши спрайты и тайлсеты имеют низкое разрешение и не должны размываться.
* Вам важна четкость и стабильность изображения при движении камеры или объектов.
**Избегайте этого, когда:** * Вы работаете с векторной или высокодетализированной растровой графикой, где сглаживание необходимо. * Вам критически важны плавные, субпиксельные движения (например, для очень медленных анимаций). Принудительное округление может сделать движение более "ступенчатым".
Помните: roundPixels — это свойство конкретной камеры. Если в игре несколько камер (например, для эффектов или UI), настройку можно применять выборочно.
Что попробовать дальше
Свойство roundPixels — это мощный и простой инструмент для борьбы с размытием в пиксель-арт играх на Phaser. В сочетании с глобальным флагом pixelArt: true в конфиге оно гарантирует сохранение острой, аутентичной пиксельной эстетики.
**Идеи для экспериментов:**
1. Попробуйте анимировать движение спрайта с дробной скоростью (например, x += 0.7) с включенным и выключенным roundPixels. Обратите внимание на разницу в плавности и четкости.
2. Создайте сцену с двумя камерами, одна из которых имеет roundPixels: true, а другая — false, и сравните вывод.
3. Поэкспериментируйте с масштабированием (setScale) спрайтов с дробными значениями при разных настройках, чтобы увидеть, как это влияет на конечное изображение.
