rexrainbow / phaser3-rex-notes

Notes of phaser3 engine
MIT License
1.22k stars 263 forks source link

GlowFilterPipelinePlugin not working with typescript #272

Closed ccmoralesj closed 2 years ago

ccmoralesj commented 2 years ago

Hey there 👋🏻

I've been trying to use GlowFilterPipelinePlugin in my Phaser app. I've tried a lot of setups, according to the official documentation and I managed to get to a good point but I'm getting a weird error. I implemented rexUI and is working like a charm, but I don't have the same luck with GlowFilterPipelinePlugin.

I've searched everywhere for a solution but I've only found the same issue here with no solution.

I'll get into detail here trying to give all the info and all the implementations I have tried. Any help will be appreciated A LOT.

thanks!

My Setup (as SCENE plugin)

Following the examples in the official documentation, I have gotten to this point implementing everything as a scene plugin.

Base class

I have a class that I use to extend all my Scenes

import RexUIPlugin from 'phaser3-rex-plugins/templates/ui/ui-plugin.js';
import GlowFilterPipelinePlugin from 'phaser3-rex-plugins/plugins/glowfilterpipeline-plugin.js';
import { FullPlayerData } from '../game/entities/FullPlayerData';
import SceneKeys from '../game/utils/SceneKeys';

export default class TFBaseScene extends Phaser.Scene {
  rexUI!: RexUIPlugin;
  rexGlow!: GlowFilterPipelinePlugin;
  playerData: FullPlayerData;

  baseEventsScene = (event: string, data?: any) =>
    this.scene.get(SceneKeys.BaseEvents).events.emit(event, data);

  constructor(key: string) {
    super({ key });
    this.playerData = FullPlayerData.getPlayerData();
  }

  restartPlayerData() {
    this.playerData = FullPlayerData.getPlayerData(true);
  }

  getPlayerData() {
    return FullPlayerData.getPlayerData();
  }
}

main.ts

import Phaser from 'phaser';
import RexUIPlugin from 'phaser3-rex-plugins/templates/ui/ui-plugin.js';
import GlowFilterPipelinePlugin from 'phaser3-rex-plugins/plugins/glowfilterpipeline-plugin.js';

import { GAME_BG_COLOR } from './game/utils/consts';
import SceneKeys from './game/utils/SceneKeys';
import BaseEventsScene from './scenes/BaseEvents';
import GameOverDialogScene from './scenes/GameOverDialog';
import GameStartDialogScene from './scenes/GameStartDialog';
import KeyboardsScene from './scenes/KeyboardsScene';
import NewLevelScene from './scenes/NewLevel';
import PanelsScene from './scenes/PanelsScene';
import PreloaderScene from './scenes/Preloader';
import ScoreScene from './scenes/ScoreScene';
import SmokeScene from './scenes/SmokeScene';
import UIElementsScene from './scenes/UIElements';

const config: Phaser.Types.Core.GameConfig = {
  type: Phaser.CANVAS,
  pixelArt: true,
  fps: {
    target: 1,
  },
  backgroundColor: GAME_BG_COLOR,
  scale: {
    width: 1920,
    height: 1080,
    mode: Phaser.Scale.FIT,
    autoCenter: Phaser.Scale.CENTER_BOTH,
  },
  plugins: {
    scene: [
      {
        key: 'rexUI',
        plugin: RexUIPlugin,
        mapping: 'rexUI',
      },
      {
        key: 'rexGlowFilterPipeline',
        plugin: GlowFilterPipelinePlugin,
        mapping: 'rexGlow',
        start: true,
      },
    ],
  },
};

const typeFightersGame = new Phaser.Game(config);

// SCENES
typeFightersGame.scene.add(SceneKeys.Preloader, PreloaderScene, true);
typeFightersGame.scene.add(SceneKeys.Preloader, BaseEventsScene);
typeFightersGame.scene.add(SceneKeys.GameStartDialog, GameStartDialogScene);
typeFightersGame.scene.add(SceneKeys.UIElements, UIElementsScene);

typeFightersGame.scene.add(SceneKeys.UIElements, ScoreScene);
typeFightersGame.scene.add(SceneKeys.NewLevel, NewLevelScene);
typeFightersGame.scene.add(SceneKeys.Keyboards, KeyboardsScene);
typeFightersGame.scene.add(SceneKeys.Panels, PanelsScene);
typeFightersGame.scene.add(SceneKeys.GameOverDialog, GameOverDialogScene);
typeFightersGame.scene.add(SceneKeys.GameOverDialog, SmokeScene);

export default typeFightersGame;

Class where I implement the base class

const makeHorizontalScoreBar = (
      x: number,
      y: number,
      color: number,
      graphics: Graphics,
      isFullLength = false
    ) => {
      const value = 100;
      graphics?.fillStyle(color, 1);
      const width = 480;
      const percent = Phaser.Math.Clamp(value, 0, 100) / 100;
      graphics?.fillRect(0, 0, width * percent, 8);
      graphics.x = x;
      graphics.y = y;
      graphics.scaleX = isFullLength ? 1 : 0;
      return graphics;
    };

const redComboBar = makeHorizontalScoreBar(
      horizontalComboBarMeasurements.x,
      horizontalComboBarMeasurements.y,
      ScoreScene.RED_COMBO_BAR_COLOR,
      redComboBarGraphic
);

const pipeline = this.rexGlow.add(redComboBar, { intensity: 0.02 });

The Error

The error I get is this one image

Once I get into the error, it seems the class doesn't have the PostFxPipelineClass (see image below) but that's not quite true because once I console.log({ rexGlow: this.rexGlow }) the PostFxPipelineClass is there. image


My Setup (as GLOBAL plugin)

Following the examples in the official documentation, I have gotten to this point by implementing everything as a global plugin.

main.ts

import Phaser from 'phaser';
import RexUIPlugin from 'phaser3-rex-plugins/templates/ui/ui-plugin.js';
import GlowFilterPipelinePlugin from 'phaser3-rex-plugins/plugins/glowfilterpipeline-plugin.js';

import { GAME_BG_COLOR } from './game/utils/consts';
import SceneKeys from './game/utils/SceneKeys';
import BaseEventsScene from './scenes/BaseEvents';
import GameOverDialogScene from './scenes/GameOverDialog';
import GameStartDialogScene from './scenes/GameStartDialog';
import KeyboardsScene from './scenes/KeyboardsScene';
import NewLevelScene from './scenes/NewLevel';
import PanelsScene from './scenes/PanelsScene';
import PreloaderScene from './scenes/Preloader';
import ScoreScene from './scenes/ScoreScene';
import SmokeScene from './scenes/SmokeScene';
import UIElementsScene from './scenes/UIElements';

const config: Phaser.Types.Core.GameConfig = {
  type: Phaser.CANVAS,
  pixelArt: true,
  fps: {
    target: 1,
  },
  backgroundColor: GAME_BG_COLOR,
  scale: {
    width: 1920,
    height: 1080,
    mode: Phaser.Scale.FIT,
    autoCenter: Phaser.Scale.CENTER_BOTH,
  },
  plugins: {
    scene: [
      {
        key: 'rexUI',
        plugin: RexUIPlugin,
        mapping: 'rexUI',
      },
    ],
    global: [
      {
        key: 'rexGlowFilterPipeline',
        plugin: GlowFilterPipelinePlugin,
        mapping: 'rexGlow',
        start: true,
      },
    ],
  },
};

const typeFightersGame = new Phaser.Game(config);

// SCENES
typeFightersGame.scene.add(SceneKeys.Preloader, PreloaderScene, true);
typeFightersGame.scene.add(SceneKeys.Preloader, BaseEventsScene);
typeFightersGame.scene.add(SceneKeys.GameStartDialog, GameStartDialogScene);
typeFightersGame.scene.add(SceneKeys.UIElements, UIElementsScene);

typeFightersGame.scene.add(SceneKeys.UIElements, ScoreScene);
typeFightersGame.scene.add(SceneKeys.NewLevel, NewLevelScene);
typeFightersGame.scene.add(SceneKeys.Keyboards, KeyboardsScene);
typeFightersGame.scene.add(SceneKeys.Panels, PanelsScene);
typeFightersGame.scene.add(SceneKeys.GameOverDialog, GameOverDialogScene);
typeFightersGame.scene.add(SceneKeys.GameOverDialog, SmokeScene);

export default typeFightersGame;

Class where I implement the base class

const makeHorizontalScoreBar = (
      x: number,
      y: number,
      color: number,
      graphics: Graphics,
      isFullLength = false
    ) => {
      const value = 100;
      graphics?.fillStyle(color, 1);
      const width = 480;
      const percent = Phaser.Math.Clamp(value, 0, 100) / 100;
      graphics?.fillRect(0, 0, width * percent, 8);
      graphics.x = x;
      graphics.y = y;
      graphics.scaleX = isFullLength ? 1 : 0;
      return graphics;
    };

const redComboBar = makeHorizontalScoreBar(
      horizontalComboBarMeasurements.x,
      horizontalComboBarMeasurements.y,
      ScoreScene.RED_COMBO_BAR_COLOR,
      redComboBarGraphic
);
const glowPlugin = this.plugins.get('rexGlow') as GlowFilterPipelinePlugin;
const pipeline = glowPlugin.add(redComboBar, { intensity: 0.02 });

The Error

the error I get is this one image

Once I get into the error I get this image

rexrainbow commented 2 years ago

Canvas render does not support shader effect. Please change type: Phaser.CANVAS to type: Phaser.WEBGL

ccmoralesj commented 2 years ago

Hey @rexrainbow, thanks for the quick response. I changed the type to Phaser.WEBGL and now my config looks like this.

const config: Phaser.Types.Core.GameConfig = {
  type: Phaser.WEBGL,
  pixelArt: true,
  fps: {
    target: 1,
  },
  backgroundColor: GAME_BG_COLOR,
  scale: {
    width: 1920,
    height: 1080,
    mode: Phaser.Scale.FIT,
    autoCenter: Phaser.Scale.CENTER_BOTH,
  },
  plugins: {
    scene: [
      {
        key: 'rexUI',
        plugin: RexUIPlugin,
        mapping: 'rexUI',
      },
      {
        key: 'rexGlowFilterPipeline',
        plugin: GlowFilterPipelinePlugin,
        mapping: 'rexGlow',
        start: true,
      },
    ],
  },
};

But I'm still getting the error:

Uncaught TypeError: Cannot read properties of undefined (reading 'resetFromJSON')

🤔

rexrainbow commented 2 years ago

GlowFilterPipelinePlugin is a global plugin, not a scene plugin. Here is a test code of GlowFilterPipelinePlugin .

ccmoralesj commented 2 years ago

It worked! I just changed it to glabl and with the WEBGL type and now I can use it pretty easily from every scene using the extends from my base class like this.rexGlow.add(gameObject, config)

I think that WEBGL type issue is something worth to have in the documentation.

Thanks a lot @rexrainbow

ccmoralesj commented 2 years ago

Great response. Just what I needed ❤️

rexrainbow commented 2 years ago

Will add more description to notify user about that. Thanks for suggestion.