О чем этот пример

При разработке ретро-игр или проектов с пиксельной стилистикой важно, чтобы графика оставалась чёткой и не размывалась при масштабировании. В Phaser 3 для этого существует специальная настройка `pixelArt`. Эта статья на практическом примере покажет, как она работает и как правильно применять её к различным типам игровых объектов — от спрайтов и тайловых карт до частиц и текста, чтобы ваша игра выглядела аутентично.

Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.

Живой запуск

Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.

Исходный код


class Example extends Phaser.Scene
{
    constructor ()
    {
        super();
        this.iter = 0;
    }

    preload ()
    {
        this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
        this.load.image('toy', 'assets/pics/shocktroopers-toy.png');
        this.load.bitmapFont('atari', 'assets/fonts/bitmap/atari-classic.png', 'assets/fonts/bitmap/atari-classic.xml');
        this.load.spritesheet('veg', 'assets/sprites/fruitnveg32wh37.png', { frameWidth: 32, frameHeight: 37 });
        this.load.image('mushroom', 'assets/sprites/mine.png');
        this.load.tilemapTiledJSON('map1', 'assets/tilemaps/maps/super-mario.json');
        this.load.image('tiles1', 'assets/tilemaps/tiles/super-mario.png');
    }

    create ()
    {
        this.tilesprite = this.add.tileSprite(400, 300, 800, 600, 'mushroom');

        const map1 = this.make.tilemap({ key: 'map1' });
        const tileset1 = map1.addTilesetImage('SuperMarioBros-World1-1', 'tiles1');
        const layer1 = map1.createLayer('World1', tileset1, 0, 64).setScale(2);

        this.add.image(0, 600, 'toy').setOrigin(0, 1).setScale(2);

        this.add.text(400, 8, 'Phaser 3 pixelArt: true', { font: '16px Courier', fill: '#00ff00' }).setOrigin(0.5, 0).setScale(3);

        this.add.particles(400, 300, 'veg', {
            frame: 0,
            speed: 100,
            frequency: 300,
            lifespan: 4000
        }).setScale(4);

        this.add.bitmapText(400, 128, 'atari', 'PHASER').setOrigin(0.5).setScale(2);
    }

    update ()
    {
        this.tilesprite.tileScaleX = Math.max(2, Math.sin(this.iter) * 8);
        this.tilesprite.tileScaleY = Math.max(2, Math.sin(this.iter) * 8);

        this.iter += 0.01;
    }
}

const config = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    parent: 'phaser-example',
    pixelArt: true,
    scene: Example
};

const game = new Phaser.Game(config);

Включаем режим Pixel Art в конфигурации

Всё начинается с главной конфигурации игры. Ключевой параметр pixelArt: true указывает Phaser отключить сглаживание (anti-aliasing) при масштабировании изображений. Это предотвращает размытие пикселей, когда вы увеличиваете спрайты или тайлы.

const config = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    parent: 'phaser-example',
    pixelArt: true, // Активация режима пиксель-арт
    scene: Example
};

Загрузка ресурсов для демонстрации

В методе preload() загружаются различные типы ресурсов, чтобы продемонстрировать эффект pixelArt на каждом из них. Обратите внимание на спрайтшит (load.spritesheet) для частиц и загрузку bitmap-шрифта (load.bitmapFont), который идеально подходит для пиксельного стиля.

preload ()
{
    this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
    this.load.image('toy', 'assets/pics/shocktroopers-toy.png');
    this.load.bitmapFont('atari', 'assets/fonts/bitmap/atari-classic.png', 'assets/fonts/bitmap/atari-classic.xml');
    this.load.spritesheet('veg', 'assets/sprites/fruitnveg32wh37.png', { frameWidth: 32, frameHeight: 37 });
    this.load.image('mushroom', 'assets/sprites/mine.png');
    this.load.tilemapTiledJSON('map1', 'assets/tilemaps/maps/super-mario.json');
    this.load.image('tiles1', 'assets/tilemaps/tiles/super-mario.png');
}

Создание и масштабирование объектов

В create() мы добавляем объекты и сразу применяем к ним масштабирование. С режимом pixelArt даже при увеличении в 2 или 4 раза (setScale) края остаются чёткими. Особенно важно это для тайловых слоев (createLayer), bitmap-текста (add.bitmapText) и систем частиц (add.particles), где размытие было бы особенно заметно.

create ()
{
    // TileSprite с текстурой гриба
    this.tilesprite = this.add.tileSprite(400, 300, 800, 600, 'mushroom');

    // Создание и масштабирование тайловой карты из Tiled
    const map1 = this.make.tilemap({ key: 'map1' });
    const tileset1 = map1.addTilesetImage('SuperMarioBros-World1-1', 'tiles1');
    const layer1 = map1.createLayer('World1', tileset1, 0, 64).setScale(2);

    // Спрайт, увеличенный в 2 раза с origin в левом нижнем углу
    this.add.image(0, 600, 'toy').setOrigin(0, 1).setScale(2);

    // Частицы, созданные из спрайтшита, увеличены в 4 раза
    this.add.particles(400, 300, 'veg', {
        frame: 0,
        speed: 100,
        frequency: 300,
        lifespan: 4000
    }).setScale(4);

    // Bitmap-текст, увеличенный в 2 раза
    this.add.bitmapText(400, 128, 'atari', 'PHASER').setOrigin(0.5).setScale(2);
}

Динамическое изменение масштаба тайлов

В update() происходит анимация TileSprite через изменение масштаба его текстуры (tileScaleX, tileScaleY). Это наглядно показывает, как режим pixelArt сохраняет чёткость даже при постоянном и динамическом изменении размера текстуры, предотвращая артефакты и размытие.

update ()
{
    // Плавное изменение масштаба тайлов на основе синусоиды
    this.tilesprite.tileScaleX = Math.max(2, Math.sin(this.iter) * 8);
    this.tilesprite.tileScaleY = Math.max(2, Math.sin(this.iter) * 8);

    this.iter += 0.01;
}

Что попробовать дальше

Настройка pixelArt: true — это простой и мощный способ сохранить стилистику пиксельной графики в Phaser 3. Она незаменима для ретро-игр, аркадных проектов или любого визуала, где важна чёткость пикселей. Для экспериментов попробуйте отключить этот режим в конфиге и сравнить результат, или примените его к своим собственным спрайтам и тайлсетам, масштабируя их в разных пропорциях.