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

Генерация равномерно распределённых объектов — частый сценарий в игровом дизайне. Например, вам нужно создать стаю рыб, пузыри или строй врагов, появляющихся на определённых позициях. Встроенный в Phaser Particle Emitter позволяет легко задавать не только линейные, но и дискретные значения для свойств частиц. В этой статье мы разберём, как использовать параметр `steps` для создания эффекта "ступенчатого" появления частиц вдоль оси Y, что идеально подходит для создания упорядоченных рядов или колонок объектов.

Версия 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.image('bg', 'assets/ui/undersea-bg.png');
        this.load.spritesheet('fish', 'assets/sprites/fish-136x80.png', { frameWidth: 136, frameHeight: 80 });
    }

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

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

        particles.createEmitter({
            frame: { frames: [ 0, 1, 2 ], cycle: true },
            x: -70,
            y: { start: 100, end: 500, steps: 8 },
            lifespan: 5000,
            speedX: 200,
            frequency: 500
        });
    }
}

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

const game = new Phaser.Game(config);

Подготовка сцены и загрузка ассетов

Вся логика примера содержится в классе сцены Example. Метод preload отвечает за загрузку изображений, необходимых для работы.

preload ()
{
    this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
    this.load.image('bg', 'assets/ui/undersea-bg.png');
    this.load.spritesheet('fish', 'assets/sprites/fish-136x80.png', { frameWidth: 136, frameHeight: 80 });
}

Первой строкой мы задаём базовый URL для загрузчиков, что позволяет указывать относительные пути к файлам. Далее загружается фоновое изображение ('bg') и спрайтшит ('fish'). Спрайтшит — это изображение, содержащее несколько кадров анимации. Параметр { frameWidth: 136, frameHeight: 80 } сообщает Phaser, как разрезать это изображение на отдельные кадры.

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

В методе create инициируются все игровые объекты. Сначала на сцену добавляется статичный фон.

create ()
{
    this.add.image(400, 300, 'bg');
    const particles = this.add.particles('fish');
}

Затем создаётся система частиц (ParticleEmitterManager), используя текстуру 'fish'. Эта система будет управлять всеми эмиттерами, испускающими частицы в виде спрайтов из этого спрайтшита.

Настройка эмиттера со ступенчатым позиционированием

Ключевой момент — создание и конфигурация самого эмиттера. Именно здесь определяется необычное поведение частиц.

particles.createEmitter({
    frame: { frames: [ 0, 1, 2 ], cycle: true },
    x: -70,
    y: { start: 100, end: 500, steps: 8 },
    lifespan: 5000,
    speedX: 200,
    frequency: 500
});

Разберём параметры: * frame: Частицы будут использовать кадры 0, 1 и 2 из спрайтшита, переключаясь между ними по циклу (cycle: true). Это создаёт простую анимацию. * `x`: Фиксированная стартовая позиция по горизонтали (-70, то есть за левой границей экрана). * `y: **Самый важный параметр.** Вместо одного числа здесь передан объект конфигурации. Частицы будут появляться на оси Y в диапазоне отstart: 100доend: 500. Параметрsteps: 8` разбивает этот диапазон на 8 равных отрезков. Каждая новая частица будет появляться на следующей "ступеньке", а не в случайном месте диапазона. * lifespan: Время жизни частицы в миллисекундах (5000 мс = 5 секунд). * speedX: Скорость движения частицы по оси X (200 пикселей в секунду). Рыбки будут плыть справа налево. * frequency: Интервал между испусканием частиц (500 мс = 0.5 секунды).

Итоговая конфигурация игры

Класс сцены необходимо передать в основную конфигурацию игры Phaser.

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

const game = new Phaser.Game(config);

Конфиг задаёт базовые параметры: использование WebGL-рендерера, разрешение окна 800x600, чёрный фон (виден до загрузки ассетов) и HTML-элемент (parent), в который будет встроен canvas. Экземпляр игры создаётся с этой конфигурацией, что запускает весь жизненный цикл.

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

Параметр steps в конфигурации свойств эмиттера — мощный инструмент для создания предсказуемых и геометрически правильных паттернов из частиц. Вместо хаотичного разброса вы получаете контроль над позициями. Для экспериментов попробуйте применить steps к другим свойствам, например, к скорости (speed) или размеру (scale), чтобы создать ряды объектов, которые меняются с каждым шагом. Или совместите ступенчатое значение по Y со случайным (random) значением по X для создания сетки частиц с небольшими смещениями.