redux 如何将Phaser集成到React中

6pp0gazn  于 2022-11-12  发布在  React
关注(0)|答案(6)|浏览(174)

我已经用create-react-app创建了一个React应用程序,我也在尝试集成Phaser 3。我按照this guide开始。我已经得到了画布渲染文本,但是在预加载中加载图像似乎不起作用。我得到了默认的加载纹理图像失败的显示。

import ExampleScene from "./scenes/ExampleScene";

import * as React from "react";

export default class Game extends React.Component {
  componentDidMount() {
    const config = {
      type: Phaser.AUTO,
      parent: "phaser-example",
      width: 800,
      height: 600,
      scene: [ExampleScene]
    };

    new Phaser.Game(config);
  }

  shouldComponentUpdate() {
    return false;
  }

  render() {
    return <div id="phaser-game" />;
  }
}

示例场景:

import Phaser from "phaser";

export default class ExampleScene extends Phaser.Scene {
  preload() {
    this.load.image("logo", "assets/logo.png");
  }
  create() {
    const text = this.add.text(250, 250, "Phaser", {
      backgroundColor: "white",
      color: "blue",
      fontSize: 48
    });

    text.setInteractive({ useHandCursor: true });
    this.add.image(400, 300, "logo");

    text.on("pointerup", () => {
      console.log("Hello!");
      //store.dispatch({ type: ACTION_TYPE });
    });
  }
}

这个想法是基于一个简单的基因引擎来创建一个可视化的花朵生长过程,这样Phaser就可以从商店得到关于当前状态的指令。
我猜这和Phaser的加载方式有关,和React的更新方式有冲突。我阻止了组件的更新,因为我只需要游戏通过听商店的指令来接收指令
我已经看过这个SO answeraccompanying wrapper,但是它已经过时了。
如何让Phaser在Create-React-App中加载图像?
程式码沙箱:https://codesandbox.io/s/github/nodes777/react-punnett/tree/phaser-game存储库:https://github.com/nodes777/react-punnett/tree/phaser-game

j0pj023g

j0pj023g1#

其他选项是使用WebComponents,以便能够将Phaser与任何其他框架(React、Angular、VueJS等)集成,请检查此npm包:https://www.npmjs.com/package/@ion-phaser/core
此外,您还可以使用该库的React Package 器轻松地将Phaser与React组件配合使用,这样就不需要直接操作WebComponents,例如:

import React from 'react'
import Phaser from 'phaser'
import { IonPhaser } from '@ion-phaser/react'

const game = {
  width: "100%",
  height: "100%",
  type: Phaser.AUTO,
  scene: {
    init: function() {
      this.cameras.main.setBackgroundColor('#24252A')
    },
    create: function() {
      this.helloWorld = this.add.text(
        this.cameras.main.centerX, 
        this.cameras.main.centerY, 
        "Hello World", { 
          font: "40px Arial", 
          fill: "#ffffff" 
        }
      );
      this.helloWorld.setOrigin(0.5);
    },
    update: function() {
      this.helloWorld.angle += 1;
    }
  }
}

const App = () => {
  return (
    <IonPhaser game={game} />
  )
}

export default App;

更多详情请查看回购协议:https://github.com/proyecto26/ion-phaser/tree/master/react

nfs0ujit

nfs0ujit2#

我从零开始,从phaser 3 template创建了my own boilerplate。我写了将React添加到Phaser 3模板here的具体步骤。
看起来你可以从Create-React-App中弹出,然后从那里添加Phaser 3,但是不要弹出的警告让我远离了这个解决方案。

vshtjzan

vshtjzan3#

一年前,我在这里寻找答案。这是一个模式,应该工作。

import Phaser from "phaser"
import React, { useEffect, useState } from "react"

/**@tutorial I made this! This answers how you get your image. */
import logoImage from "./path-to-logo.png"

/**@tutorial I made this! Use a functional React component and `useEffect` hook.*/
export const Phaser3GameComponent = ({ someState }) => {
  // Optional: useful to delay appearance and avoid canvas flicker.
  const [isReady, setReady] = useState(false)
  // Just an example... do what you do here. 
  const dataService = (changedState) => {
    // I'm not sure how to use stores, but you'll know better what to do here.
    store.dispatch(
      {
        ...someState,
        ...changedState,
      },
      { type: ACTION_TYPE }
    )
  }
  // This is where the fun starts. 
  useEffect(() => {
    const config = {
      callbacks: {
        preBoot: game => {
          // A good way to get data state into the game.
          game.registry.merge(someState)
          // This is a good way to catch when that data changes.
          game.registry.events.on("changedata", (par, key, val, prevVal) => {
            // Simply call whatever functions you want outside.
            dataService({ [key]: val })
          })
        },
      },
      type: Phaser.AUTO,
      parent: "phaser-example",
      width: 800,
      height: 600,
      scene: [ExampleScene],
    }
    let game = new Phaser.Game(config)
    // Triggered when game is fully READY.
    game.events.on("READY", setReady)
    // If you don't do this, you get duplicates of the canvas piling up.
    return () => {
      setReady(false)
      game.destroy(true)
    }
  }, []) // Keep the empty array otherwise the game will restart on every render.
  return (
    <div id="phaser-example" className={isReady ? "visible" : "invisible"} />
  )
}

export default class ExampleScene extends Phaser.Scene {
  preload() {
    this.load.image("logo", logoImage)
  }
  create() {
    // You made this!
    const text = this.add.text(250, 250, "Phaser")
    text.setInteractive({ useHandCursor: true })
    this.add.image(400, 300, "logo")
    /**@tutorial I made this! */
    // Get all that lovely dataState into your scene,
    let { clickCount } = this.registry.getAll()
    text.on("pointerup", () => {
      // This will trigger the "changedata" event handled by the component.
      this.registry.merge({ clickCount: clickCount++ })
    })
    // This will trigger the scene as now being ready.
    this.game.events.emit("READY", true)
  }
}
ycggw6v2

ycggw6v24#

您需要将图片放入文件夹 public 中!

nimxete2

nimxete25#

对我来说,我看到的最好的做法,以使用这两个正确的是创建phaser项目单独主机使用firebase或任何主机服务,你喜欢单独,然后采取的链接,并把它放在一个iframe标签内react.这样你就可以有效地管理他们,你可以操纵react网站在更舒适的方式,特别是移动的宽度兼容性.

rt4zxlrg

rt4zxlrg6#

在我的例子中,我使用了以下组件,它工作正常:

import Phaser from 'phaser';
import * as React from 'react';

import { HTML_DIV_ID, gameConfig } from './gameConfig';

export const GameWrapper = () => {
    const [game, setGame] = React.useState<Phaser.Game>();

    React.useEffect(() => {
        const _game = new Phaser.Game(gameConfig());

        setGame(_game);

        return (): void => {
            _game.destroy(true);
            setGame(undefined);
        };
    }, []);

    return (
        <>
            <div id={HTML_DIV_ID} />
        </>
    );
};

使用创建React应用程序和React严格模式:
此外,我删除了React.StrictMode(create-react-app的默认选项),因为它挂载和卸载所有组件,所以我有时会遇到相位器的意外行为

相关问题