О чем этот пример
TileSprite (плиточный спрайт) в Phaser — отличный инструмент для создания бесшовных текстурных фонов или бесконечно повторяющихся паттернов. Чаще всего они используются как статичный декор. Но что, если оживить их, добавив реалистичную физику? В этой статье мы разберем, как превратить обычный TileSprite в полноценный физический объект с помощью плагина Matter.js. Это открывает двери к созданию динамических игровых миров: вращающихся платформ с анимированной текстурой, разрушающихся плиточных стен или фонов, реагирующих на действия игрока.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
iter = 0;
sprite2;
sprite1;
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('platform', 'assets/sprites/platform.png');
this.load.image('mushroom', 'assets/sprites/mushroom2.png');
this.load.image('balls', 'assets/sprites/balls.png');
}
create ()
{
this.sprite1 = this.add.tileSprite(100, 100, 150, 150, 'mushroom');
this.sprite2 = this.add.tileSprite(0, -100, 200, 51, 'balls');
this.matter.add.gameObject(this.sprite1).setFrictionAir(0.001).setBounce(0.8);
this.matter.add.gameObject(this.sprite2).setFrictionAir(0.001).setBounce(0.8);
this.matter.add.image(350, 500, 'platform', null, { isStatic: true }).setScale(2, 0.5).setAngle(9);
}
update ()
{
this.sprite1.tilePositionX = Math.cos(this.iter) * 400;
this.sprite1.tilePositionY = Math.sin(this.iter) * 400;
this.sprite2.tilePositionX = Math.cos(-this.iter) * 200;
this.sprite2.tilePositionY = Math.sin(-this.iter) * 200;
this.iter += 0.01;
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#1b1464',
parent: 'phaser-example',
physics: {
default: 'matter',
matter: {
debug: true,
gravity: {
y: 0.3
}
}
},
scene: Example
};
const game = new Phaser.Game(config);
Создание сцены и загрузка ассетов
Как и в любой сцене Phaser, мы начинаем с методов preload и create. В preload загружаются три изображения, которые будут использоваться в качестве текстур для спрайтов и платформы.
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('platform', 'assets/sprites/platform.png');
this.load.image('mushroom', 'assets/sprites/mushroom2.png');
this.load.image('balls', 'assets/sprites/balls.png');
}
В методе create создаются два ключевых объекта: sprite1 и sprite2. Обратите внимание, что для их создания используется метод this.add.tileSprite. В отличие от обычного this.add.image, tileSprite принимает параметры ширины и высоты (150, 150 и 200, 51), определяющие область, которая будет заполнена повторяющейся (плиткуемой) текстурой. Эти спрайты изначально не имеют физического тела.
create ()
{
this.sprite1 = this.add.tileSprite(100, 100, 150, 150, 'mushroom');
this.sprite2 = this.add.tileSprite(0, -100, 200, 51, 'balls');
}
Превращаем TileSprite в физическое тело
Самый важный шаг — добавление физического тела Matter.js к уже существующему объекту TileSprite. Для этого используется фабричный метод this.matter.add.gameObject(). Этот метод принимает игровой объект (в нашем случае this.sprite1 и this.sprite2) и возвращает его же, но уже с прикрепленным к нему физическим телом.
this.matter.add.gameObject(this.sprite1).setFrictionAir(0.001).setBounce(0.8);
this.matter.add.gameObject(this.sprite2).setFrictionAir(0.001).setBounce(0.8);
Сразу после создания тела мы можем настроить его физические свойства через цепочку вызовов. setFrictionAir(0.001) устанавливает очень низкое сопротивление воздуха, позволяя объектам долго парить. setBounce(0.8) задает высокий коэффициент упругости (отскока).
Далее создается статичная платформа, которая будет служить землей. Для нее используется метод this.matter.add.image, который сразу создает и спрайт, и физическое тело. Ключевой параметр { isStatic: true } делает тело неподвижным. setScale и setAngle изменяют ее размер и угол наклона.
this.matter.add.image(350, 500, 'platform', null, { isStatic: true }).setScale(2, 0.5).setAngle(9);
Анимация текстуры в реальном времени
Магия TileSprite раскрывается в методе update. Пока физический движок Matter.js рассчитывает столкновения, гравитацию и движение тел, мы можем независимо анимировать текстуру внутри каждого TileSprite, изменяя его свойства tilePositionX и tilePositionY.
update ()
{
this.sprite1.tilePositionX = Math.cos(this.iter) * 400;
this.sprite1.tilePositionY = Math.sin(this.iter) * 400;
this.sprite2.tilePositionX = Math.cos(-this.iter) * 200;
this.sprite2.tilePositionY = Math.sin(-this.iter) * 200;
this.iter += 0.01;
}
Здесь используется простая тригонометрическая функция для создания кругового движения текстуры. Переменная this.iter увеличивается на 0.01 каждый кадр, выступая в роли угла. Значения tilePosition смещают начало координат текстуры, создавая иллюзию ее плавного скольжения внутри границ спрайта. Важно понимать, что это не двигает само физическое тело, а только его визуальное наполнение.
Настройка физического движка Matter
Вся физика работает благодаря конфигурации движка в объекте config. В блоке physics указывается default: 'matter', что активирует плагин Matter.js. Вложенный объект matter позволяет задать дополнительные параметры.
physics: {
default: 'matter',
matter: {
debug: true,
gravity: {
y: 0.3
}
}
}
- debug: true включает отладочную отрисовку: видны контуры физических тел (прямоугольники для TileSprite), что помогает визуализировать коллайдеры.
- gravity: { y: 0.3 } задает слабую вертикальную гравитацию, заставляющую наши TileSprite-шары постепенно падать на наклонную платформу.
Что попробовать дальше
Сочетание плиточной анимации TileSprite и реалистичной физики Matter.js создает мощный эффект «живых» объектов. Вы можете экспериментировать: попробуйте менять физические свойства (mass, friction) в реальном времени, создавать составные тела из TileSprite или анимировать tileScale для эффекта «зыбкой» или пульсирующей текстуры на движущихся платформах. Это отличный способ добавить глубины и интерактивности игровому окружению.
