О чем этот пример
В процессе разработки игры на Phaser вы можете столкнуться с ситуацией, когда объект отрисовывается не так, как ожидалось. Эта статья разбирает конкретный пример с методом `stamp` для `RenderTexture`, где вместо спрайта на экране появляется белый квадрат. Понимание причины этой проблемы и её решения поможет вам увереннее работать с динамической отрисовкой и избегать подобных ошибок в своих проектах.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Game extends Phaser.Scene {
constructor() {
super({
key: 'Game'
})
}
// preload() {
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
// this.load.image('mushroom', 'assets/sprites/mushroom.png');
// }
create() {
var rt = this.add.renderTexture(400, 300, 200, 200);
rt.stamp('__WHITE', undefined, 0, 0, {scale: 10});
}
}
var config = {
type: Phaser.AUTO,
parent: 'phaser-example',
width: 800,
height: 600,
scale: {
// mode: Phaser.Scale.FIT,
// autoCenter: Phaser.Scale.CENTER_BOTH,
},
backgroundColor: '#0a0067',
scene: Game,
};
var game = new Phaser.Game(config);
Анализ проблемы: Почему квадрат белый?
Центральная проблема данного кода заключается в попытке использовать текстуру по её внутреннему ключу '__WHITE' напрямую в методе stamp. Метод stamp ожидает получить либо строковый ключ загруженного изображения, либо экземпляр игрового объекта (например, Sprite).
Ключ '__WHITE' — это внутренний ресурс движка, однотонный белый пиксель, который используется для различных операций рендеринга. Однако, как показывает пример, он не предназначен для прямого использования в stamp в качестве строкового аргумента, если соответствующее изображение не было явно загружено. В результате вместо ожидаемого спрайта на RenderTexture отрисовывается белый прямоугольник.
rt.stamp('__WHITE', undefined, 0, 0, {scale: 10});
Решение 1: Загрузка готового спрайта
Самый прямой и правильный способ — загрузить нужное изображение через preload и использовать его ключ. Это стандартный рабочий процесс в Phaser. Нужно раскомментировать блок preload и загрузку изображения, а в stamp передать ключ 'mushroom'.
preload() {
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('mushroom', 'assets/sprites/mushroom.png');
}
create() {
var rt = this.add.renderTexture(400, 300, 200, 200);
rt.stamp('mushroom', undefined, 0, 0, {scale: 10});
}
После этого на RenderTexture будет отштампован увеличенный спрайт гриба, а не белый квадрат.
Решение 2: Использование игрового объекта
Метод stamp также может принимать в качестве первого параметра не строку, а сам игровой объект. Это открывает возможность для динамического создания спрайтов, в том числе и на основе внутренней текстуры '__WHITE', если создать из неё объект Image.
create() {
var rt = this.add.renderTexture(400, 300, 200, 200);
// Создаем спрайт на основе внутренней белой текстуры
var whiteSprite = this.add.image(0, 0, '__WHITE').setVisible(false);
// Штампуем сам объект, а не строковый ключ
rt.stamp(whiteSprite, 0, 0, {scale: 10});
}
В этом случае whiteSprite — это полноценный игровой объект типа Image. Мы создаём его с координатами (0,0) и сразу скрываем (setVisible(false)), чтобы он не отображался на основном игровом слое, а использовался только для штампа. Такой подход даёт больше контроля, например, можно предварительно настроить цвет или другие свойства объекта.
Ключевой вывод по API
Важно запомнить разницу в использовании метода `stamp`:
1. **Режим строки (ключ текстуры)**: `rt.stamp('key')`. Требует предварительной загрузки ассета с этим ключом через `this.load`.
2. **Режим объекта (Game Object)**: `rt.stamp(gameObject)`. Требует создания экземпляра объекта (например, через `this.add.image`). Объект может быть видимым или невидимым на основной сцене.
Попытка использовать внутренний ключ движка '__WHITE' в строковом режиме без его явной загрузки приводит к некорректному результату.
Что попробовать дальше
Проблема с белым квадратом возникает из-за несоответствия между ожиданиями метода RenderTexture.stamp и переданным ему аргументом. Для её решения достаточно следовать одному из двух стандартных паттернов: либо загружать ресурсы заранее, либо создавать и настраивать игровые объекты. Для экспериментов попробуйте заменить '__WHITE' на другие внутренние ключи (например, '__DRAW'), штамповать несколько разных объектов на одну RenderTexture или анимировать параметры штампа (такие как alpha или tint) в цикле update.
