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

Создание игрового мира — это не только расстановка готовых спрайтов. Часто нужны объекты со своей логикой и предустановленными свойствами. В этой статье разберем, как создавать собственные классы игровых объектов, наследуясь от стандартных классов Phaser. Это позволяет инкапсулировать логику, повторно использовать код и создавать сложные иерархии сущностей, делая код чище и масштабируемее.

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

Живой запуск

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

Исходный код


class EnemyRobot extends Phaser.GameObjects.Image {

    constructor (scene, x, y)
    {
        super(scene, x, y);

        this.setTexture('contra');
        this.setPosition(x, y);
        this.setScale(2);
    }

}

var config = {
    type: Phaser.AUTO,
    parent: 'phaser-example',
    scene: {
        preload: preload,
        create: create
    }
};

var game = new Phaser.Game(config);

function preload ()
{
        this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
    this.load.image('contra', 'assets/pics/contra3.png');
}

function create ()
{
    this.children.add(new EnemyRobot(this, 264, 250));
    this.children.add(new EnemyRobot(this, 464, 350));
    this.children.add(new EnemyRobot(this, 664, 450));
}

Зачем свои классы?

Представьте, что в игре десятки одинаковых врагов. Копировать код настройки для каждого — неэффективно и чревато ошибками. Гораздо лучше описать врага один раз в виде класса, а затем создавать его экземпляры.

Кастомный класс позволяет: * **Группировать настройки**: Размер, текстура, физические свойства задаются в конструкторе. * **Добавлять логику**: В дальнейшем в класс можно добавить методы для анимации, стрельбы, получения урона. * **Упрощать создание**: Инициализация нового врага сводится к одному вызову new.

В примере мы создаем класс EnemyRobot, который является расширением стандартного Phaser.GameObjects.Image.

Создаем класс-наследник

Ключевой момент — использование синтаксиса ES6 class и ключевого слова extends. Это указывает, что наш EnemyRobot будет обладать всеми свойствами и методами игрового изображения (Image).

class EnemyRobot extends Phaser.GameObjects.Image {
    constructor (scene, x, y)
    {
        super(scene, x, y);

        this.setTexture('contra');
        this.setPosition(x, y);
        this.setScale(2);
    }
}
Разберем конструктор:
1.  `super(scene, x, y);` — Вызов конструктора родительского класса (`Image`). Это обязательный первый шаг. Он регистрирует объект в текущей сцене `scene` и задает его начальные координаты.
2.  `this.setTexture('contra');` — Указывает ключ текстуры, загруженной в `preload`. Объект будет отображать эту картинку.
3.  `this.setPosition(x, y);` — Явно устанавливает позицию. Хотя она уже передана в `super()`, это хорошая практика для ясности.
4.  `this.setScale(2);` — Увеличивает спрайт в 2 раза. Это уже кастомное свойство нашего робота.

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

Конфигурация игры и загрузка ресурсов остаются стандартными. Обратите внимание, что в preload мы загружаем изображение по ключу 'contra', который затем используем в классе.

function preload ()
{
    this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
    this.load.image('contra', 'assets/pics/contra3.png');
}

Конфиг игры указывает на функции preload и create.

var config = {
    type: Phaser.AUTO,
    parent: 'phaser-example',
    scene: {
        preload: preload,
        create: create
    }
};

var game = new Phaser.Game(config);

Добавляем объекты на сцену

В функции create происходит магия. Мы создаем экземпляры нашего класса и добавляем их в список дочерних объектов сцены через this.children.add(). Каждый робот автоматически получает все заданные в конструкторе свойства.

function create ()
{
    this.children.add(new EnemyRobot(this, 264, 250));
    this.children.add(new EnemyRobot(this, 464, 350));
    this.children.add(new EnemyRobot(this, 664, 450));
}

Важно: new EnemyRobot(this, 464, 350) — здесь первый аргумент this (сцена) передается в конструктор класса. Метод this.children.add() регистрирует объект в системе отображения Phaser.

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

Создание собственных классов игровых объектов — фундаментальный шаг к структурированной и мощной кодовой базе в Phaser. Вы не ограничены изображениями: можно наследоваться от Sprite, Container или даже PhysicsImage. Для экспериментов попробуйте добавить в класс метод update() для автоматического движения врага, реализовать параметр здоровья (this.health) или создать иерархию классов (например, базовый Enemy и наследующие от него EnemyRobot и EnemyAlien).