Integrating React and Phaser 3 Tutorial

Taylor Nodell
Apr 15, 2019 · 3 min read

While building a fun little punnett square in React, I wanted to expand to include some visualizations in a game engine. Phaser is one of the top JavaScript based game engines, however I found few resources that combined the most popular front end framework with this game engine. A wrapper exists for Phaser CE but it’s a bit outdated and I wanted to use Phaser 3. And this tutorial gets both running, but isn’t able to run the Preload function. I also followed a webpack tutorial for setting up React manually. Using these resources, these are my steps to get React up with Phaser 3.

Phaser and React Logos

The tech: React, Babel, Webpack, Phaser 3, Node, NPM

Here’s the final template repo.

  1. First we’ll clone the Phaser 3 Project template. I use this as the base rather than Create-React-App because we can config the webpack set up, rather than having to eject from Create-React-App.
  2. Run npm i path babel-preset-react to install dependencies. The Phaser 3 template comes with babel-core but not the preset for React.

3) Now we’ll need to update our webpack config. In webpack/base.js we’ll add entry and output keys and include rules for JSX and CSS. We’ll also include filename and inject keys for our HtmlWebpackPlugin.

module.exports = {
mode: "development",
devtool: "eval-source-map",
entry: "./src/index.js",
output: {
path: path.resolve("dist"),
filename: "index_bundle.js"
},
module: {
rules: [
{
test: /\.css$/,
use: [{ loader: "style-loader" }, { loader: "css-loader" }]
},
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: "babel-loader"
},
{
test: [/\.vert$/, /\.frag$/],
use: "raw-loader"
},
{
test: /\.(gif|png|jpe?g|svg|xml)$/i,
use: "file-loader"
}
]
},
plugins: [
new CleanWebpackPlugin(["dist"], {
root: path.resolve(__dirname, "../")
}),
new webpack.DefinePlugin({
CANVAS_RENDERER: JSON.stringify(true),
WEBGL_RENDERER: JSON.stringify(true)
}),
new HtmlWebpackPlugin({
template: "./index.html",
filename: "index.html",
inject: "body"
})
]
};

5) Update .babelrc to include “@babel/preset-react” as a preset. I changed mine to be a .babelrc.js so my editor would automatically format it.

const presets = [
[
"@babel/env",
{
targets: {
browsers: [">0.25%", "not ie 11", "not op_mini all"]
},
modules: false
}
],
"@babel/preset-react"
];
const plugins = [];
module.exports = { presets, plugins };

6) Now we can finally add a React component. Let’s make a folder for those, components/App.jsx.

import React from "react";export default class App extends React.Component {
render() {
return (
<div style={{ textAlign: "center" }}>
<h1>Hello World</h1>
</div>
);
}
}

7) Because src/index.js is our entry point we’ll need to render our component there with ReactDOM.render. From here we can grow our code base both in React and Phaser!

import Phaser from "phaser";
import logoImg from "./assets/logo.png";
import React from "react";
import ReactDOM from "react-dom";
import App from "./components/App.jsx";
const config = {
type: Phaser.AUTO,
parent: "phaser-example",
width: 800,
height: 600,
scene: {
preload: preload,
create: create
}
};
const game = new Phaser.Game(config);function preload() {
this.load.image("logo", logoImg);
}
function create() {
const logo = this.add.image(400, 150, "logo");
this.tweens.add({
targets: logo,
y: 450,
duration: 2000,
ease: "Power2",
yoyo: true,
loop: -1
});
}
ReactDOM.render(<App />, document.getElementById("root"));

And that’s it! Running npm start will open up a browser with the Phaser Logo and your React component at the top of the page.

Our Page on Localhost:8080

More From Medium

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade