Анимация параметров шейдера

Phaser предоставляет мощные возможности для работы с графикой через шейдеры, позволяя создавать визуально сложные эффекты и динамическую анимацию. Центральной задачей является управление uniform-параметрами шейдера, которые определяют его поведение, такие как цвета, интенсивность эффектов, смещения текстур и другие свойства.


Подключение пользовательского шейдера

Для начала необходимо создать класс шейдера. Phaser поддерживает как GLSL-фрагментные шейдеры, так и интеграцию с материалами через Phaser.GameObjects.Shader.

Пример создания кастомного шейдера:

class CustomShader extends Phaser.GameObjects.Shader {
    constructor(scene) {
        super(scene, 'customShader', `
            precision mediump float;
            uniform float uTime;
            uniform vec2 uResolution;
            void main() {
                vec2 uv = gl_FragCoord.xy / uResolution.xy;
                float color = 0.5 + 0.5 * sin(uTime + uv.x * 10.0);
                gl_FragColor = vec4(vec3(color), 1.0);
            }
        `, {
            uTime: 0,
            uResolution: { x: 800, y: 600 }
        });
        scene.add.existing(this);
    }
}

В этом примере создаётся простая анимация цвета, зависящая от времени (uTime) и координат пикселя. Uniform-параметры uTime и uResolution можно изменять динамически для создания эффектов анимации.


Управление параметрами через сцену

Phaser позволяет обновлять uniform-параметры шейдера в методе update сцены. Это основной способ реализовать плавные анимации и синхронизацию с игровым циклом.

class MainScene extends Phaser.Scene {
    constructor() {
        super({ key: 'MainScene' });
    }

    preload() {}

    create() {
        this.shader = new CustomShader(this);
        this.startTime = this.time.now;
    }

    update(time, delta) {
        const elapsed = (time - this.startTime) / 1000; // секунды
        this.shader.setUniform('uTime', elapsed);
    }
}

Ключевой момент — расчёт времени в секундах, что обеспечивает консистентную анимацию независимо от частоты кадров.


Использование Tween для параметров шейдера

Для сложных эффектов удобно использовать встроенные возможности Phaser для анимации через tweens. Это позволяет плавно изменять значения uniform-параметров по заданной кривой.

this.tweens.add({
    targets: this.shader.uniforms,
    uIntensity: 1.0,
    duration: 2000,
    yoyo: true,
    repeat: -1,
    ease: 'Sine.easeInOut'
});
  • targets — объект, содержащий uniform-параметры.
  • yoyo и repeat обеспечивают бесконечное чередование эффекта.
  • ease контролирует кривую изменения параметра.

Такой подход идеально подходит для анимации вспышек, пульсаций, искажения текстур и других визуальных эффектов.


Связывание параметров с игровыми объектами

Uniform-параметры шейдера можно связывать с положением или состоянием игровых объектов:

this.shader.setUniform('uMouse', { x: this.input.x / this.scale.width, y: this.input.y / this.scale.height });

Это позволяет реализовать эффекты реагирования на движение мыши или касания, создавая интерактивную анимацию.

Для объектов в пространстве сцены часто используют координаты спрайтов:

this.shader.setUniform('uPlayerPos', { x: player.x, y: player.y });

Такой подход полезен для эффектов освещения, магических аур или зон влияния.


Анимация через Math-функции и циклы

Кроме tween, анимации можно создавать через тригонометрические функции для периодических изменений:

const intensity = 0.5 + 0.5 * Math.sin(time / 500);
this.shader.setUniform('uIntensity', intensity);
  • sin/cos позволяют получать плавное циклическое изменение параметра.
  • Можно комбинировать несколько функций для сложных паттернов:
const wave = Math.sin(time / 400) + Math.cos(time / 700);
this.shader.setUniform('uWave', wave);

Адаптивная анимация под разрешение экрана

Для корректного отображения шейдеров важно передавать разрешение сцены:

this.shader.setUniform('uResolution', { x: this.scale.width, y: this.scale.height });

При изменении размеров окна (resize) uniform-параметр нужно обновлять, чтобы сохранить пропорции и корректность анимации.

this.scale.on('resize', (gameSize) => {
    this.shader.setUniform('uResolution', { x: gameSize.width, y: gameSize.height });
});

Использование текстур и тайлинга

Uniform-параметры могут включать текстуры для создания динамических эффектов:

this.shader.setUniform('uTexture', someSprite.texture);
this.shader.setUniform('uTileOffset', { x: 0, y: time / 1000 });

Это позволяет анимировать движение текстур, эффекты волн, скроллинг фонов или искажение спрайтов.


Оптимизация производительности

  • Обновлять uniform-параметры только при необходимости, избегая лишних вызовов.
  • Для сложных эффектов использовать offscreen canvas и рендер текстур, чтобы снизить нагрузку.
  • Стараться минимизировать вычисления в update, предварительно рассчитывая значения через формулы или tween.

Phaser предоставляет гибкую систему управления шейдерами, позволяя создавать эффектные анимации через uniform-параметры, интегрировать их с игровыми объектами, использовать tween и тригонометрические функции для плавных визуальных эффектов. Правильное управление параметрами и оптимизация обновлений обеспечивают высокую производительность и интерактивность графики.