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

Работая с движком Phaser, разработчики часто используют спрайты и тайл-спрайты для графики. Однако стандартный `TileSprite` не имеет физического тела 'из коробки', что ограничивает его интерактивность. В этой статье мы разберем, как добавить физическое тело к TileSprite, чтобы он мог сталкиваться, отскакивать и реагировать на границы мира. Этот прием полезен для создания динамических фонов, разрушаемых стен или крупных составных объектов, состоящих из повторяющихся текстур.

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

    create ()
    {
        //  Our dynamic TileSprite that will bounce around
        const block = this.add.tileSprite(100, 100, 32 * 4, 32 * 2, 'crate');

        this.physics.add.existing(block, false);

        block.body.setVelocity(130, 180);
        block.body.setBounce(1, 1);
        block.body.setCollideWorldBounds(true);

        //  Our static TileSprite that will just receive collide events
        const staticBlock = this.add.tileSprite(400, 300, 32 * 3, 32 * 8, 'crate');

        this.physics.add.existing(staticBlock, true);

        this.physics.add.collider(block, staticBlock);
    }
}

const config = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    parent: 'phaser-example',
    physics: {
        default: 'arcade',
        arcade: {
            debug: true,
            gravity: { y: 200 }
        }
    },
    scene: Example
};

const game = new Phaser.Game(config);

Проблема: TileSprite без физики

Класс TileSprite в Phaser отлично подходит для отображения повторяющихся текстур — например, для кирпичной стены, травяного поля или крупного объекта, собранного из одного изображения. По умолчанию он является статическим графическим объектом.

const staticBlock = this.add.tileSprite(400, 300, 32 * 3, 32 * 8, 'crate');

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

Решение: Добавление физического тела

Phaser Arcade Physics предоставляет метод this.physics.add.existing(), который добавляет физическое тело к уже существующему игровому объекту. Это ключевой момент для 'оживления' TileSprite.

// Добавляем динамическое тело (второй параметр - false)
this.physics.add.existing(block, false);

// Добавляем статическое тело (второй параметр - true)
this.physics.add.existing(staticBlock, true);

Параметр isStatic определяет тип тела. Динамическое тело (false) будет двигаться под действием сил и столкновений. Статическое тело (true) остается неподвижным, но может участвовать в коллизиях.

Настройка динамического тела

После добавления тело становится доступным через свойство .body. Для динамического тела мы можем задать начальную скорость, упругость и включить столкновение с границами игрового мира.

block.body.setVelocity(130, 180); // Устанавливаем скорость по осям X и Y
block.body.setBounce(1, 1); // Задаем коэффициент отскока (1 - абсолютно упругий удар)
block.body.setCollideWorldBounds(true); // Включаем столкновение с границами сцены

Эти настройки заставляют наш тайл-спрайт двигаться, отскакивать от краев экрана и в конечном итоге — от других физических объектов.

Организация взаимодействий

Чтобы объекты реагировали друг на друга, нужно создать коллайдер. Метод this.physics.add.collider() регистрирует столкновение между двумя телами и обрабатывает его.

this.physics.add.collider(block, staticBlock);

В нашем примере динамический block будет отскакивать от статического staticBlock. Без этого вызова объекты могли бы проходить друг сквозь друга, несмотря на наличие физических тел.

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

Важно не забыть активировать Arcade Physics в конфигурации игры. Без этого любые вызовы методов физики будут приводить к ошибкам.

const config = {
    type: Phaser.AUTO,
    width: 800,
    height: 600,
    physics: { // Включаем физический движок
        default: 'arcade',
        arcade: {
            debug: true, // Полезно для отладки: рисует контуры тел
            gravity: { y: 200 } // Глобальная сила тяжести
        }
    },
    scene: Example
};

Параметр debug: true временно включает визуализацию hitbox, что помогает убедиться в правильности размеров и положений тел.

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

Добавление физического тела к TileSprite — мощный прием, который значительно расширяет возможности этого графического объекта. Вы можете создавать движущиеся платформы с текстурой, разрушаемые стены из кирпичей или скроллящиеся фоны, взаимодействующие с игроком. Для экспериментов попробуйте изменить размеры тайл-спрайтов, поиграть с коэффициентами отскока или заставить несколько динамических блоков сталкиваться между собой, создавая сложные физические симуляции.