Phaser - Need Rive (animator) support

Could there be a future plugin to integrate Rive (already supported on Defold 2D Game Engine)

2 Likes

That’s the only thing missing for my company, that keeps us from using phaser

really or just kidding? :thinking:

sadly no. When I joined they went with rive and konva. Throwing in a phaser layer here and there, but it’s really a pain. Now that I think about it… one could render the rive offscreen and somehow copy every texture/frame into phaser somehow. but I will also need to map the clicks…ahrg


ok, that did not take long!

quick protoype:

this.canvas = document.createElement('canvas');

    this.riveInstance = new rive.Rive({
      // Load a local riv `clean_the_car.riv` or upload your own!
      src: hamster,
      // Be sure to specify the correct state machine (or animation) name
      stateMachines: 'State Machine 1', // Name of the State Machine to play
      canvas: this.canvas,
      layout: layout, // This is optional. Provides additional layout control.
      autoplay: true,
      onLoad: () => {
        // Prevent a blurry canvas by using the device pixel ratio
        this.riveInstance.resizeDrawingSurfaceToCanvas();
      },
    });
    document.body.appendChild(this.canvas);
    this.canvas.width = 200; // Set your desired width
    this.canvas.height = 200; // Set your desired height

    setTimeout(() => {
      // Add the canvas to the Phaser game
      this.texture = this.textures.addCanvas('canvasTexture', this.canvas);

      // Now you can use 'canvasTexture' as any other Phaser texture
      let image = this.add.image(0, 0, 'canvasTexture').setOrigin(0, 0);
      const barrel = image.preFX.addBarrel(1);
      this.add.tween({
        duration: Phaser.Math.Between(400, 500),
        repeatDelay: Phaser.Math.Between(100, 200),
        targets: barrel,
        ease: 'Sine.easeInOut',
        amount: 0.786,
        yoyo: true,
        repeat: -1,
      });
      // Enable input on the image
      image.setInteractive();
      // Get the inputs via the name of the state machine
      const inputs = this.riveInstance.stateMachineInputs('State Machine 1');
      // Add a pointer down event
      image.on('pointerdown', (pointer) => {
        if (!this.riveInstance) return;

        // Get the local y-coordinate of the pointer relative to the image
        let localY = pointer.y - image.y;

        // Calculate the height of each third of the image
        let thirdHeight = image.height / 3;

        let animationName;
        // Check which third was clicked
        if (localY < thirdHeight) {
          console.log('First third clicked');
          animationName = inputs.find((i) => i.name === hamsterEvents.TOUCH_1);
        } else if (localY < 2 * thirdHeight) {
          console.log('Second third clicked');
          animationName = inputs.find((i) => i.name === hamsterEvents.TOUCH_2);
        } else {
          console.log('Third third clicked');
          animationName = inputs.find((i) => i.name === hamsterEvents.TOUCH_3);
        }

        animationName.fire();
      });
    }, 1000);```

And just draw the new frame over it

 update() {
    if (this.texture) {
      const ctx = this.texture.context;
      // Draw the external canvas onto the texture
      ctx.drawImage(this.canvas, 0, 0, this.texture.width, this.texture.height);
      this.texture.refresh();
    }
  }

Any performance hints welcome. Not sure how expensive this is