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

Создание реалистичных эффектов частиц — ключ к визуальному богатству игры. Phaser 3 предоставляет мощный Particle Emitter, который умеет не только красиво рисовать, но и взаимодействовать с миром. В этой статье мы разберем, как заставить частицы отскакивать от границ, создавая динамичные и живые эффекты, такие как фейерверки, искры или магические всплески. Мы рассмотрим конкретный пример с настройкой физических свойств эмиттера, что позволит вам легко адаптировать этот код для своих нужд — будь то ограничение частиц определенной зоной или создание сложных траекторий с учетом столкновений.

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

Живой запуск

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

Исходный код


class Example extends Phaser.Scene
{
    preload ()
    {
        this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
        this.load.atlas('flares', 'assets/particles/flares.png', 'assets/particles/flares.json');
    }

    create ()
    {
        const particles = this.add.particles('flares');

        const emitter = particles.createEmitter({
            frame: [ 'red', 'green' ],
            x: 400,
            y: 400,
            lifespan: 4000,
            angle: { min: 225, max: 315 },
            speed: { min: 300, max: 500 },
            scale: { start: 0.6, end: 0 },
            gravityY: 300,
            bounce: 0.9,
            bounds: { x: 250, y: 0, w: 350, h: 0 },
            collideTop: false,
            collideBottom: false,
            blendMode: 'ADD'
        });
    }
}

const config = {
    type: Phaser.WEBGL,
    width: 800,
    height: 600,
    backgroundColor: '#000',
    parent: 'phaser-example',
    scene: Example
};

const game = new Phaser.Game(config);

Подготовка атласа частиц

Вся графика для частиц в Phaser часто загружается в виде атласа — одного изображения, содержащего несколько кадров (спрайтов) и JSON-файла с их координатами. Это эффективно для производительности.

В методе preload мы загружаем такой атлас с именем 'flares'. Базовая ссылка задается для удобства, а сами файлы — изображение flares.png и данные flares.json — содержат набор разноцветных вспышек.

this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.atlas('flares', 'assets/particles/flares.png', 'assets/particles/flares.json');

Создание системы частиц и эмиттера

В методе create мы создаем менеджер частиц и в нем — конкретный эмиттер. Менеджер (this.add.particles) отвечает за рендеринг всех связанных с ним эмиттеров.

Эмиттер настраивается через объект конфигурации. Ключевые параметры, задающие его поведение: * frame: Кадры из атласа, которые будут использоваться (здесь красный и зеленый). * x, y: Точка испускания частиц. * lifespan: Время жизни частицы в миллисекундах. * angle и speed: Направление и скорость разлета. * scale: Изменение размера от начала к концу жизни. * gravityY: Симуляция гравитации, притягивающей частицы вниз. * blendMode: Режим наложения 'ADD' для яркого, светящегося эффекта.

const particles = this.add.particles('flares');

const emitter = particles.createEmitter({
    frame: [ 'red', 'green' ],
    x: 400,
    y: 400,
    lifespan: 4000,
    angle: { min: 225, max: 315 },
    speed: { min: 300, max: 500 },
    scale: { start: 0.6, end: 0 },
    gravityY: 300,
    bounce: 0.9,
    bounds: { x: 250, y: 0, w: 350, h: 0 },
    collideTop: false,
    collideBottom: false,
    blendMode: 'ADD'
});

Коллизии и отскок частиц

Самый важный для нашей цели блок параметров — это настройка физики столкновений. Именно он заставляет частицы отскакивать.

* bounds: Определяет невидимый прямоугольник, от границ которого будут отскакивать частицы. Важно: параметр h: 0 в данном примере делает высоту зоны равной высоте игрового мира. Частицы будут сталкиваться с левой (x: 250) и правой (x + w = 600) стенками этой зоны. * bounce: Коэффициент упругости (от 0 до 1). Значение 0.9 означает очень упругий, энергичный отскок с минимальной потерей скорости. * collideTop и collideBottom: Отключены (false). Это значит, что частицы НЕ будут сталкиваться с верхней и нижней границей мира (или зоны bounds). Они свободно пролетают вверх и вниз, но отскакивают от боковых стенок, создавая эффект "фонтана" или "разлета вбок".

Без параметра bounds и включенных коллизий частицы просто пролетали бы сквозь границы экрана.

Настройка сцены и запуск игры

Код завершается стандартной для Phaser 3 конфигурацией игры. Мы указываем использование WebGL для рендеринга (частицы на Canvas тоже работают, но WebGL обычно быстрее), размеры окна, цвет фона и связываем конфиг с описанным выше классом сцены Example.

const config = {
    type: Phaser.WEBGL,
    width: 800,
    height: 600,
    backgroundColor: '#000',
    parent: 'phaser-example',
    scene: Example
};

const game = new Phaser.Game(config);

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

Вы разобрали пример, который превращает простой поток частиц в физически правдоподобную систему с отскоками. Основная сила — в комбинации bounds, bounce и селективном включении коллизий через collideTop/Bottom/Left/Right. Для экспериментов попробуйте: 1. Изменить bounds, чтобы создать коридор или замкнутую коробку для частиц. 2. Включить collideBottom: true и посмотреть, как частицы начнут скапливаться на "полу". 3. Поиграть со значением bounce (например, 0.2 для "вялых" отскоков или 1.1 для нереалистичного, но зрелищного ускорения). 4. Добавить несколько эмиттеров с разными точками испускания и цветами, чтобы создать сложный составной эффект.