О чем этот пример
Создание динамического игрового мира — ключ к захватывающему геймплею. В этой статье разберем, как оживить фон с помощью плавной интерполяции цвета камеры в зависимости от положения игрока. Этот прием отлично подходит для создания иллюзии глубины в платформерах, смены времени суток или простого визуального сопровождения движения героя. Вы научитесь использовать встроенные инструменты Phaser для работы с цветом и геометрией, не прибегая к тяжелым ассетам.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
constructor ()
{
super();
}
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('star', 'assets/demoscene/star2.png');
this.load.image('dude', 'assets/sprites/phaser-dude.png');
}
create ()
{
this.w = this.cameras.main.width;
this.h = this.cameras.main.height;
var bg = this.add.group({ key: 'star', frameQuantity: 300 });
this.sky = new Phaser.Display.Color(120, 120, 255);
this.space = new Phaser.Display.Color(0, 0, 0);
this.player = this.add.sprite(this.w / 2, 0, 'dude');
this.cameras.main.startFollow(this.player);
var rect = new Phaser.Geom.Rectangle(0, -2 * this.h, this.w, 2 * this.h);
Phaser.Actions.RandomRectangle(bg.getChildren(), rect);
}
update ()
{
this.player.y = (Math.cos(this.time.now / 1000) * (this.h - 10)) - this.h;
var hexColor = Phaser.Display.Color.Interpolate.ColorWithColor(this.sky, this.space, -this.h * 2, this.player.y);
this.cameras.main.setBackgroundColor(hexColor);
}
}
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 800,
height: 600,
scene: Example
};
const game = new Phaser.Game(config);
Настройка сцены и загрузка ресурсов
В методе preload мы загружаем два изображения: спрайт игрока (dude) и текстуру звезды (star), которая будет использована для создания фоновых частиц.
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('star', 'assets/demoscene/star2.png');
this.load.image('dude', 'assets/sprites/phaser-dude.png');
}
Создание мира: звезды, игрок и цвета
В create подготавливается игровое пространство. Сначала мы сохраняем ширину и высоту основной камеры в переменные this.w и this.h для удобства.
Затем создается группа (Group) из 300 звезд, используя загруженную текстуру.
var bg = this.add.group({ key: 'star', frameQuantity: 300 });
Определяются два целевых цвета для интерполяции: светло-голубой (sky) для верхней части и черный (space) для нижней. Создается спрайт игрока и размещается по центру по горизонтали вверху экрана. Камера начинает следовать за игроком с помощью this.cameras.main.startFollow(this.player).
this.sky = new Phaser.Display.Color(120, 120, 255);
this.space = new Phaser.Display.Color(0, 0, 0);
this.player = this.add.sprite(this.w / 2, 0, 'dude');
this.cameras.main.startFollow(this.player);
Звезды случайным образом распределяются по большому прямоугольнику, который расположен выше видимой области, создавая эффект звездного поля.
var rect = new Phaser.Geom.Rectangle(0, -2 * this.h, this.w, 2 * this.h);
Phaser.Actions.RandomRectangle(bg.getChildren(), rect);
Анимация и магия интерполяции цвета
Вся динамика происходит в методе update. Положение игрока по оси Y задается косинусоидой, зависящей от времени, что заставляет его плавно колебаться между верхом и низом экрана.
this.player.y = (Math.cos(this.time.now / 1000) * (this.h - 10)) - this.h;
Самое интересное — расчет цвета фона. Функция Phaser.Display.Color.Interpolate.ColorWithColor плавно смешивает два цвета (sky и space) на основе текущей позиции игрока (this.player.y). Третий аргумент — минимальное значение диапазона (здесь -this.h * 2), четвертый — максимальное (здесь this.player.y). Таким образом, когда игрок внизу (значение Y ближе к 0), цвет ближе к черному (space), а когда наверху (значение Y меньше), цвет ближе к голубому (sky).
var hexColor = Phaser.Display.Color.Interpolate.ColorWithColor(this.sky, this.space, -this.h * 2, this.player.y);
Полученный цвет применяется как фон основной камеры.
this.cameras.main.setBackgroundColor(hexColor);
Что попробовать дальше
Мы реализовали плавную смену фона, которая реагирует на движение игрока, используя всего несколько строчек кода и встроенный API Phaser. Этот прием можно расширить: например, интерполировать между несколькими цветами для сложных градиентов, привязать изменение цвета не к позиции игрока, а к игровому времени для цикла дня и ночи, или менять цвет фона при переходе между уровнями. Экспериментируйте с параметрами интерполяции и источниками данных для создания уникальной атмосферы в вашей игре.
