О чем этот пример
В разработке игр часто требуется визуализировать движение: следы за снарядом, шлейф за персонажем или, как в нашем примере, плавный след за курсором мыши. Эта статья покажет, как эффективно использовать объекты `Phaser.Math.Vector2` и их метод `copy()` для создания такого эффекта без лишнего потребления памяти. Вы научитесь переиспользовать объекты в пуле, что критически важно для оптимизации производительности в играх с большим количеством визуальных частиц.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
create ()
{
const graphics = this.add.graphics({ fillStyle: { color: 0x2266aa } });
const points = [];
for (let k = 0; k < 150; k++)
{
points.push(new Phaser.Math.Vector2());
}
let i = 0;
this.input.on('pointermove', pointer =>
{
// const vector2 = points[i];
points[i].copy(pointer);
i = (i + 1) % points.length;
graphics.clear();
graphics.fillPointShape(pointer, 25);
for (let j = 0; j < points.length; j++)
{
points[j].x += 4 + Math.abs(j - 75) / 15;
graphics.fillPointShape(points[j], 25);
}
});
}
}
const config = {
width: 800,
height: 600,
type: Phaser.AUTO,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Суть метода copy()
Метод copy() объекта Phaser.Math.Vector2 копирует координаты (свойства `xиy) из одного вектора в другой. Это гораздо эффективнее, чем постоянно создавать новые объектыnew Phaser.Math.Vector2(x, y)` при каждом движении курсора, что приводит к частым операциям сборки мусора и падению FPS.
Вместо создания нового объекта, мы берём уже существующий вектор из заранее созданного массива и обновляем его данные, используя вектор-источник (в данном случае — объект pointer).
Подготовка: пул точек и слушатель события
Код начинает работу с создания графического контекста graphics для отрисовки и массива points, который выступает в роли пула (набора заранее созданных объектов). Этот массив заполняется 150 "пустыми" векторами.
Затем создаётся слушатель события движения курсора pointermove. Переменная `i` используется как индекс текущего вектора в пуле, который будет обновлён следующим.
const graphics = this.add.graphics({ fillStyle: { color: 0x2266aa } });
const points = [];
for (let k = 0; k < 150; k++) {
points.push(new Phaser.Math.Vector2());
}
let i = 0;
this.input.on('pointermove', pointer => {
// ... логика обработки
});
Обновление точек и создание шлейфа
Внутри обработчика события происходит магия. Сначала координаты курсора копируются в текущий вектор из пула.
points[i].copy(pointer);
Затем индекс `iсдвигается по кругу с помощью операции взятия остатка от деления (%`). Это гарантирует, что когда мы дойдём до конца массива из 150 элементов, следующий индекс снова станет равным 0. Таким образом, мы постоянно перезаписываем самую "старую" точку в шлейфе.
i = (i + 1) % points.length;
Перед отрисовкой нового кадра холст очищается, и отрисовывается большая точка в текущей позиции курсора.
graphics.clear();
graphics.fillPointShape(pointer, 25);
Анимация шлейфа: движение и отрисовка
Чтобы точки шлейфа не стояли на месте, а плавно двигались вправо, для каждой точки в массиве применяется смещение по оси X. Смещение зависит от индекса точки `j`, создавая волнообразный эффект: точки ближе к центру шлейфа (индекс 75) двигаются медленнее, чем точки по краям.
После обновления позиции каждая точка отрисовывается.
for (let j = 0; j < points.length; j++) {
points[j].x += 4 + Math.abs(j - 75) / 15;
graphics.fillPointShape(points[j], 25);
}
Ключевой момент: мы изменяем координаты `xу тех же самых объектов векторов, которые хранятся в пулеpoints`. Новые объекты не создаются, что и обеспечивает высокую производительность.
Что попробовать дальше
Использование пула объектов Vector2 и метода copy() — это фундаментальный паттерн оптимизации для создания динамических визуальных эффектов в Phaser. Попробуйте изменить формулу смещения (points[j].x += ...), чтобы шлейф улетал вверх, закручивался по спирали или реагировал на скорость движения курсора. Экспериментируйте с размером пула и размером отрисовываемых точек, чтобы создать эффекты огненного хвоста, магического следа или частиц дыма.
