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

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

Версия 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('bg', 'assets/skies/darkstone.png');
        this.load.image('platform', 'assets/particles/platform.png');
        this.load.image('slime', 'assets/particles/slime.png');
    }

    create ()
    {
        this.add.image(400, 300, 'bg');

        //  Picks a random value between the first and second array elements
        this.add.particles(0, 0, 'slime', {
            x: { random: [ 80, 720 ] },
            lifespan: 2500,
            gravityY: 200,
            frequency: 80,
            scale: { min: 0.6, max: 1.1 },
            blendMode: 'ADD'
        });

        this.add.image(-100, 0, 'platform').setOrigin(0, 0);
        this.add.image(412, 0, 'platform').setOrigin(0, 0);
    }
}

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

const game = new Phaser.Game(config);

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

Всё начинается с метода preload. Здесь мы загружаем три изображения, которые будут использоваться в сцене. Обратите внимание на использование this.load.setBaseURL() — это удобный способ задать базовый путь для всех последующих загрузок, что избавляет от необходимости писать полные URL для каждого ресурса.

preload ()
{
    this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
    this.load.image('bg', 'assets/skies/darkstone.png');
    this.load.image('platform', 'assets/particles/platform.png');
    this.load.image('slime', 'assets/particles/slime.png');
}

Первое изображение ('bg') станет фоном. Второе ('platform') — частью статичного окружения. А ключевой ресурс для нашей системы частиц — это текстура 'slime', которая будет использоваться для каждой создаваемой частицы.

Создание сцены: фон и декорации

В методе create мы сначала размещаем фоновое изображение по центру области отображения. Координаты (400, 300) соответствуют центру холста размером 800x600 пикселей, заданного в конфигурации игры.

this.add.image(400, 300, 'bg');

Затем мы добавляем два изображения платформ. Использование метода setOrigin(0, 0) устанавливает точку привязки (origin) изображения в его левый верхний угол. Это позволяет легко позиционировать их, начиная от координат (-100, 0) и (412, 0), создавая иллюзию длинной платформы, разорванной посередине.

this.add.image(-100, 0, 'platform').setOrigin(0, 0);
this.add.image(412, 0, 'platform').setOrigin(0, 0);

Сердце примера: конфигурация эмиттера частиц

Самая важная часть кода — это создание эмиттера частиц с помощью метода this.add.particles(). Первые три аргумента — это начальные координаты эмиттера (0, 0) и ключ текстуры ('slime').

Четвертый аргумент — это объект конфигурации, определяющий поведение всех частиц в этом эмиттере.

this.add.particles(0, 0, 'slime', {
    x: { random: [ 80, 720 ] },
    lifespan: 2500,
    gravityY: 200,
    frequency: 80,
    scale: { min: 0.6, max: 1.1 },
    blendMode: 'ADD'
});
Давайте разберем каждый параметр:
*   `x: { random: [80, 720] }` — это ключевой параметр для нашей задачи. Вместо фиксированного значения, координата X для рождающейся частицы будет выбираться случайным образом из диапазона между 80 и 720 пикселями. Это создает эффект, будто частицы появляются по всей ширине экрана, а не из одной точки.
*   `lifespan: 2500` — время жизни частицы в миллисекундах (2.5 секунды).
*   `gravityY: 200` — сила гравитации, которая будет тянуть частицы вниз, создавая эффект падения.
*   `frequency: 80` — интервал между испусканием частиц в миллисекундах. Частица будет создаваться каждые 80 мс.
*   `scale: { min: 0.6, max: 1.1 }` — масштаб каждой частицы также будет случайным в заданном диапазоне, добавляя визуальное разнообразие.
*   `blendMode: 'ADD'` — режим наложения цвета. `'ADD'` делает яркие области (как у текстуры `slime`) еще ярче при наложении, создавая эффект свечения.

Запуск игры: базовая конфигурация

Код вне класса Example содержит стандартную конфигурацию объекта игры Phaser. Мы указываем тип рендерера (Phaser.AUTO), размеры холста, цвет фона (который будет перекрыт нашим изображением), ID родительского HTML-элемента и нашу сцену.

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

const game = new Phaser.Game(config);

Инициализация new Phaser.Game(config) создает и запускает игровой экземпляр, который начинает выполнять жизненный цикл нашей сцены (preload, create, update).

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

Использование объекта { random: [min, max] } для свойств эмиттера — это мощный и элегантный способ внести разнообразие в систему частиц, не усложняя логику сцены. Phaser сам обрабатывает случайность при создании каждой новой частицы. Для экспериментов попробуйте применить тот же принцип к другим свойствам: задайте случайный angle для разлета частиц веером, speedY для разной скорости падения или tint для разноцветного эффекта. Вы можете комбинировать несколько случайных свойств в одном эмиттере, чтобы создать чрезвычайно сложные и живые визуальные эффекты с минимальным количеством кода.