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

Одной из ключевых механик в играх часто является взаимодействие с объектами: кликните на врага — он умирает, нажмите на предмет — он исчезает. В этом примере мы разберем, как легко реализовать уничтожение спрайтов по нажатию мыши в Phaser 3, используя событие `gameobjectdown` и метод `destroy()`. Это базовый, но мощный паттерн, который можно адаптировать для создания кликабельных интерфейсов, головоломок или экшен-игр.

Версия 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.atlas('cards', 'assets/atlas/cards.png', 'assets/atlas/cards.json');
    }

    create ()
    {
        this.createCards();

        this.input.on('gameobjectdown', (pointer, gameObject) =>
        {

            gameObject.destroy();

        });
    }

    createCards ()
    {
        const frames = this.textures.get('cards').getFrameNames();

        for (let i = 0; i < 64; i++)
        {
            const x = Phaser.Math.Between(0, 800);
            const y = Phaser.Math.Between(0, 600);
            const s = Phaser.Math.FloatBetween(0.5, 1);

            this.add.image(x, y, 'cards', Phaser.Math.RND.pick(frames)).setScale(s).setInteractive();
        }
    }
}

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

const game = new Phaser.Game(config);

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

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

preload ()
{
    this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
    this.load.atlas('cards', 'assets/atlas/cards.png', 'assets/atlas/cards.json');
}

Создание интерактивных спрайтов

В методе create вызывается функция createCards, которая генерирует 64 случайные карты на поле. Каждый спрайт создается с помощью this.add.image. Ключевой момент здесь — вызов метода .setInteractive() для каждого изображения. Без этого спрайт не будет реагировать на ввод пользователя, и событие gameobjectdown не сработает.

createCards ()
{
    const frames = this.textures.get('cards').getFrameNames();

    for (let i = 0; i < 64; i++)
    {
        const x = Phaser.Math.Between(0, 800);
        const y = Phaser.Math.Between(0, 600);
        const s = Phaser.Math.FloatBetween(0.5, 1);

        this.add.image(x, y, 'cards', Phaser.Math.RND.pick(frames)).setScale(s).setInteractive();
    }
}

Обработка клика и уничтожение объекта

Сердце примера — обработчик события gameobjectdown. Это событие генерируется системой ввода Phaser (this.input) при нажатии (например, левой кнопкой мыши) на любой игровой объект, который является интерактивным. Обработчик получает два аргумента: указатель (pointer) и сам игровой объект (gameObject), по которому кликнули.

this.input.on('gameobjectdown', (pointer, gameObject) =>
{
    gameObject.destroy();
});

Вызов gameObject.destroy() полностью удаляет объект из игры: он убирается со сцены, его текстура освобождается, и он больше не участвует в физических расчетах (если бы они были). Это эффективный способ убрать ненужные элементы.

Конфигурация и запуск игры

Как и в любом проекте на Phaser 3, нам нужна конфигурация игры (config), где мы задаем базовые параметры, такие как тип рендерера, размеры холста и указываем нашу сцену. После этого создается экземпляр игры new Phaser.Game(config), который запускает весь процесс.

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

const game = new Phaser.Game(config);

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

Вы научились создавать интерактивные спрайты и мгновенно удалять их по клику. Это основа для множества игровых механик. Для экспериментов попробуйте

  1. Добавить анимацию или эффект частиц перед вызовом destroy() для более плавного исчезновения
  2. Использовать событие gameobjectup для других типов взаимодействий
  3. Проверять тип объекта (gameObject.texture.key) перед уничтожением, чтобы, например, удалять только карты определенной масти