О чем этот пример
При создании множества игровых объектов ручное задание координат и свойств для каждого становится рутиной. Phaser предлагает элегантный способ декларативного создания спрайтов через конфигурационные объекты. Этот подход не только делает код чище, но и позволяет использовать мощные функции для случайной генерации значений прямо в конфиге, что идеально подходит для создания процедурного контента, частиц или случайно сгенерированных уровней.
Версия 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('bunny', 'assets/sprites/bunny.png');
this.load.image('atari', 'assets/sprites/atari400.png');
this.load.image('logo', 'assets/sprites/phaser2.png');
}
create ()
{
// Implicit values
const config1 = {
key: 'bunny',
x: 400,
y: 300
};
// Implicit values
const config2 = {
key: 'bunny',
x: 400,
y: 300,
flipX: true,
flipY: true
};
// An array means 'pick one element at random'
const config3 = {
key: [ 'bunny', 'atari', 'logo' ],
x: 400,
y: 300
};
// randInt means pick a random integer between the min and max values given
const config4 = {
key: 'atari',
x: { randInt: [ 0, 800 ] },
y: 300
};
// randFloat means pick a random float between the min and max values given
const config5 = {
key: 'logo',
x: 400,
y: 300,
alpha: { randFloat: [ 0.1, 1 ] }
};
// If the property is a function it will invoke it and use the result as the value
const config6 = {
key: 'atari',
x: 400,
y: function ()
{
return 100 + Math.random() * 500;
}
};
// An example using randFloat to set the scale of a Sprite
const config7 = {
key: 'logo',
x: 400,
y: 300,
scale: { randFloat: [ 0.2, 2 ] }
};
// An example using randFloat to set independent x and y scale values
const config8 = {
key: 'logo',
x: 400,
y: 300,
scale: { x: { randFloat: [ 0.2, 2 ] }, y: { randFloat: [ 1.5, 3 ] } }
};
this.make.sprite(config8);
}
}
const config = {
type: Phaser.WEBGL,
parent: 'phaser-example',
width: 800,
height: 600,
scene: Example
};
const game = new Phaser.Game(config);
Базовый принцип: `this.make.sprite(config)`
Ключевой метод для работы — this.make.sprite(). Он принадлежит фабрике игровых объектов (GameObjectFactory), доступной в сцене как this.make. Вместо передачи параметров по отдельности, вы передаёте один конфигурационный объект.
Этот подход централизует логику создания объекта. Вы можете заранее подготовить массив конфигов и создать сразу несколько разнообразных спрайтов в цикле, что гораздо удобнее, чем множество отдельных вызовов.
// Создание спрайта с базовыми свойствами
const config = {
key: 'bunny',
x: 400,
y: 300
};
this.make.sprite(config);
Случайный выбор текстуры и простые флаги
Конфиг умеет больше, чем задавать статические значения. Например, для свойства key можно передать массив строк. Phaser выберет одну из текстур случайным образом. Это полезно для создания разнообразия, когда нужны похожие, но не идентичные объекты (разные типы деревьев, облаков, врагов).
Также можно напрямую задавать булевы свойства, такие как отражение по осям, используя flipX и flipY.
// Случайный выбор одной из трёх текстур
const config3 = {
key: [ 'bunny', 'atari', 'logo' ],
x: 400,
y: 300
};
// Отражение спрайта по обеим осям
const config2 = {
key: 'bunny',
x: 400,
y: 300,
flipX: true,
flipY: true
};
Генерация случайных чисел: `randInt` и `randFloat`
Для динамического заполнения числовых свойств Phaser предоставляет специальные инструкции randInt (случайное целое) и randFloat (случайное дробное). Их нужно передавать как объект с ключом-инструкцией и массивом [min, max] в качестве значения.
Это мощный инструмент для разброса объектов по сцене (`x,y), настройки визуальных эффектов (alpha,rotation) или изменения размера (scale`).
// Случайная позиция X в диапазоне от 0 до 800
const config4 = {
key: 'atari',
x: { randInt: [ 0, 800 ] },
y: 300
};
// Случайная прозрачность от почти невидимой до полной
const config5 = {
key: 'logo',
x: 400,
y: 300,
alpha: { randFloat: [ 0.1, 1 ] }
};
Использование функций для вычисления значений
Самая гибкая опция — использование функции в качестве значения свойства. Phaser вызовет эту функцию в момент создания спрайта и подставит возвращённый результат. Это открывает безграничные возможности: сложные математические расчёты, привязку к другим объектам на сцене или генерацию значений по нелинейным законам.
// Позиция Y вычисляется функцией
const config6 = {
key: 'atari',
x: 400,
y: function ()
{
return 100 + Math.random() * 500;
}
};
Продвинутое применение: случайный масштаб по осям
Инструкции и функции можно комбинировать для сложных свойств. Например, свойство scale может быть как одним числом (равномерный масштаб), так и объектом с независимыми значениями для `xиy. В каждое из этих вложенных свойств также можно передатьrandFloat` или функцию.
Это позволяет создавать объекты, сжатые или растянутые случайным образом, что добавляет натуральности группе объектов (например, камням или кустам).
// Равномерный случайный масштаб
const config7 = {
key: 'logo',
x: 400,
y: 300,
scale: { randFloat: [ 0.2, 2 ] }
};
// Независимый случайный масштаб по осям X и Y
const config8 = {
key: 'logo',
x: 400,
y: 300,
scale: { x: { randFloat: [ 0.2, 2 ] }, y: { randFloat: [ 1.5, 3 ] } }
};
Что попробовать дальше
Создание спрайтов через конфигурационные объекты превращает рутинную работу в гибкий и мощный инструмент. Вы можете описывать целые наборы объектов с вариациями в стиле данных, что идеально для прототипирования и процедурной генерации. Для экспериментов попробуйте: создать «россыпь» звёзд на небе, используя randInt для X и Y; задать случайный угол поворота (angle) для обломков; или написать функцию для свойства tint, которая будет возвращать случайный цвет из палитры вашей игры.
