О чем этот пример

В процессе разработки игры на 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.