О чем этот пример
При создании игр часто возникает необходимость динамически менять внешний вид объектов: персонаж надевает новую броню, предметы трансформируются или фон меняется при смене локации. Рендеринг множества спрайтов с разными текстурами может быть затратным. В этой статье вы научитесь использовать мощный и малоизвестный метод `setSource()` для мгновенной подмены графики у уже созданных объектов, что открывает возможности для оптимизации и создания интересных визуальных эффектов без создания новых текстурных объектов.
Версия 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('piggy', 'assets/pics/pigchampagne.png');
this.load.image('atari', 'assets/sprites/atari130xe.png');
}
create ()
{
const piggy = this.add.image(400, 300, 'piggy');
const textureA = this.textures.get('piggy');
const textureB = this.textures.get('atari');
this.input.on('pointerdown', () => {
textureA.setSource(textureB.source);
});
}
}
const config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 800,
height: 600,
scene: Example
};
const game = new Phaser.Game(config);
Зачем это нужно? Проблема и решение
Представьте, что у вас есть объект (например, спрайт персонажа), и вам нужно мгновенно изменить его внешний вид на другой. Самый очевидный способ — создать новый спрайт с другой текстурой и удалить старый. Однако это не всегда эффективно, особенно если переключений много.
Метод texture.setSource() предлагает альтернативу. Вместо замены спрайта мы заменяем источник данных (пиксели) у самой текстуры. Все объекты, использующие эту текстуру, мгновенно обновятся. Это похоже на замену холста, на котором нарисовано изображение, при этом сам фрейм (текстура в памяти Phaser) остаётся прежним.
Разбираем пример: Загрузка и получение текстур
Вначале в методе preload() загружаются два изображения с присвоением им уникальных ключей.
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('piggy', 'assets/pics/pigchampagne.png');
this.load.image('atari', 'assets/sprites/atari130xe.png');
}
В create() создаётся изображение piggy. Затем с помощью менеджера текстур this.textures получаем ссылки на объекты текстур, а не на спрайты.
create ()
{
const piggy = this.add.image(400, 300, 'piggy');
const textureA = this.textures.get('piggy');
const textureB = this.textures.get('atari');
}
textureA — это объект текстуры, которую сейчас использует изображение piggy. textureB — текстура, которую мы хотим использовать в качестве нового источника.
Волшебный щелчок: Использование setSource
Вся магия происходит по клику мыши. Мы назначаем текстуре textureA (с ключом 'piggy') источник данных от текстуры textureB (с ключом 'atari').
this.input.on('pointerdown', () => {
textureA.setSource(textureB.source);
});
Важно понять, что меняется именно внутренний источник (source) — данные изображения. Ключ текстуры textureA остаётся 'piggy', но теперь она выглядит как 'atari'. Изображение piggy на сцене мгновенно меняет свою картинку. Если бы на сцене было несколько объектов с текстурой 'piggy', все они бы синхронно обновились.
Важные нюансы и ограничения API
1. **Размер и формат:** Phaser не масштабирует источник под размер целевой текстуры. Если новый источник имеет другие пропорции, изображение может отобразиться некорректно. Убедитесь, что текстуры имеют одинаковые или подходящие размеры.
2. **Кэширование:** Замена источника не затрагивает кэш загрузчика (this.load). Ключ 'piggy' в кэше всё ещё будет вести на исходное изображение поросёнка.
3. **Область видимости:** Метод setSource() работает с объектом типа Phaser.Textures.Texture. Источник (source) — это свойство такого объекта, обычно это HTMLImageElement или Canvas.
4. **Производительность:** Эта операция очень быстрая, так как не требует пересоздания GPU-текстуры, а лишь обновляет её данные.
Практическое применение в играх
Вот несколько идей, где это может быть полезно: * **Аватары и снаряжение:** У вас есть базовая текстура персонажа. При надевании шлема вы подменяете источник текстуры шлема на текстуру шлема другого вида. * **Эффекты состояния:** Текстура здорового дерева мгновенно меняется на текстуру срубленного пня. * **Оптимизация частиц:** Можно иметь одну текстуру частицы и менять её источник для создания разнообразных эффектов (огонь, дым, звёзды), не создавая сотни отдельных текстурных объектов. * **Динамические интерфейсы:** Создание кнопок, иконки которых меняются в зависимости от контекста.
Пример смены снаряжения:
// Предположим, textureBaseArmor — текстура для слота брони на персонаже.
// textureNewArmor — текстура новой брони из инвентаря.
equipButton.on('pointerdown', () => {
textureBaseArmor.setSource(textureNewArmor.source);
});
Что попробовать дальше
Метод setSource() — это скрытый gem в API Phaser для работы с текстурами. Он позволяет динамически и эффективно менять визуальное представление объектов, что полезно для систем кастомизации, визуальных эффектов и оптимизации. Для экспериментов попробуйте создать анимацию, плавно переключая источники между несколькими текстурами по таймеру, или реализуйте простой редактор спрайтов, где игрок может комбинировать части изображений.
